You need to enable JavaScript to run this app.
导航
进阶功能
最近更新时间:2024.12.17 17:08:49首次发布时间:2022.01.17 10:33:21

本章节介绍了拉流 SDK 进阶功能的接入方式,支持的进阶功能包括但不限于 RTM 协议拉流、QUIC 协议拉流、使用 IP 地址拉流、使用主备流、多档位切换、自适应码率(ABR)拉流、截图、SEI、以及订阅视频和音频数据。您可以根据实际业务需求,借助拉流 SDK 实现更复杂的功能。

前提条件

注意事项

真机调试:由于 SDK 使用了大量 Android 系统的音视频接口,这些接口在仿真模拟器下可能会出现异常,推荐您使用真机进行代码调试。

功能接入

本节为您详细介绍如何使用拉流 SDK 进阶功能的实现,包括但不限于 RTM 协议拉流、QUIC 协议拉流、使用 IP 地址拉流、使用主备流、多档位切换、自适应码率(ABR)拉流、截图、SEI、以及订阅视频和音频数据。

RTM 协议拉流

视频直播拉流 SDK 支持 RTM 协议拉流,该功能需要配合火山引擎视频直播服务使用。详细信息可参考超低延时直播介绍

注意

RTM 协议拉流不支持纯音频或纯视频流。

接入准备

  • 确认已集成 1.37.1 及以上版本的互动版拉流 SDK。
  • 使用视频直播控制台的地址生成器,生成 RTM 和 FLV 拉流地址,其中,FLV 地址可作为 RTM 拉流失败时的自动降级地址。

接入说明

配置 RTM 拉流地址和 FLV 拉流地址进行播放。代码示例如下所示。

// 配置 RTM 地址
VeLivePlayerStream playStreamRTM = new VeLivePlayerStream();
playStreamRTM.url = "https://pull.example.com/live/stream.sdp";
playStreamRTM.format = VeLivePlayerFormatRTM;
playStreamRTM.resolution = VeLivePlayerResolutionOrigin;
playStreamRTM.streamType = VeLivePlayerStreamTypeMain;

// 配置 FLV 地址
VeLivePlayerStream playStreamFLV = new VeLivePlayerStream();
playStreamFLV.url = "https://pull.example.com/live/stream.flv";
playStreamFLV.format = VeLivePlayerFormatFLV;
playStreamFLV.resolution = VeLivePlayerResolutionOrigin;
playStreamFLV.streamType = VeLivePlayerStreamTypeMain;

// 创建 VeLivePlayerStreamData
VeLivePlayerStreamData streamData = new VeLivePlayerStreamData();
streamData.mainStreamList = new ArrayList<>();

// 添加 RTM 流地址
streamData.mainStreamList.add(playStreamRTM);

// 添加 FLV 流地址
streamData.mainStreamList.add(playStreamFLV);

// 配置默认 format 和 protocol
streamData.defaultFormat = VeLivePlayerFormatRTM;
streamData.defaultProtocol = VeLivePlayerProtocolTLS;

// 配置播放源
mLivePlayer.setPlayStreamData(streamData);

// 开始播放
mLivePlayer.play();

QUIC 协议拉流

视频直播拉流 SDK 支持 QUIC 协议拉流,该功能需要配合火山引擎视频直播服务使用。

接入准备

使用视频直播控制台的地址生成器,生成 FLV 拉流地址。

接入说明

配置 QUIC 拉流地址进行播放。代码示例如下所示。

// 配置 FLV 流地址
VeLivePlayerStreamData.VeLivePlayerStream playStreamFLV = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamFLV.url = "https://pull.example.com/live/stream.flv";
playStreamFLV.format = VeLivePlayerFormatFLV;
playStreamFLV.resolution = VeLivePlayerResolutionOrigin;
playStreamFLV.streamType = VeLivePlayerStreamTypeMain;

// 创建播放源
VeLivePlayerStreamData streamData = new VeLivePlayerStreamData();
streamData.mainStreamList = new ArrayList<>();

// 添加 FLV 流
streamData.mainStreamList.add(playStreamFLV);

// 配置默认 format 和 protocol
streamData.defaultFormat = VeLivePlayerFormatFLV;
streamData.defaultProtocol = VeLivePlayerProtocolQUIC; // 协议为 QUIC

// 配置播放源
mLivePlayer.setPlayStreamData(streamData);

// 开始播放
mLivePlayer.play();

说明

拉流 SDK 默认开启了 QUIC 协议拉流的失败降级策略,无需额外配置。如果 QUIC 协议拉流失败,SDK 将自动降级为 TCP 协议拉流。

使用 IP 地址拉流

播放器支持通过设置播放域名的 IP 地址进行拉流,以降低播放首帧时间。

接入准备

请先获取直播播放地址并解析出 IP 地址。

注意事项

  • 使用 setUrlHostIP 对域名和 IP 地址进行映射时,需在初始化配置中关闭 DNS 预解析功能,即 enableLiveDNS 设置为 false。
  • 需要在调用 play 开始播放前,调用本方法设置域名和 IP 的映射。

接入说明

使用播放器的 setUrlHostIP 接口将 IP 地址与域名关联起来,播放器将直接根据 IP 地址进行拉流播放。代码示例如下所示。

// 配置播放 URL
mLivePlayer.setPlayUrl("https://pull.example.com/live/stream.flv");
// 添加 IP 地址和域名关联
List<String> valueList = new ArrayList<>();
valueList.add("xxx.xxx.xxx.xxx"); // IP 地址
Map<String, List<String>> map = new HashMap<>();
map.put("pull.example.com", valueList);

// 配置 IP 地址
mLivePlayer.setUrlHostIP(map);

// 开始播放
mLivePlayer.play();

使用主备流

主备流主要用于直播间容灾,通过配置主备两路直播流地址,在推流和分发环节使用主备流进行直播。播放器在接入时配置主备两路拉流地址,当主路地址拉流失败或者播放出错时,播放器会自动切换到备路地址进行播放。同样地,当备路地址播放出错时,播放器会切换回主路地址进行播放。主备地址可以来自同一直播服务商,也可以来自不同的直播服务商。

接入准备

获取主流地址和备流地址,如果使用火山引擎视频直播服务,您可通过视频直播控制台的地址生成器,生成主备拉流地址。

接入说明

  1. 配置主备流地址进行播放。代码示例如下所示。
// 配置主流地址
VeLivePlayerStreamData.VeLivePlayerStream playStreamMain = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamMain.url = "https://pull.example.com/live/主.flv";
playStreamMain.format = VeLivePlayerFormatFLV;
playStreamMain.resolution = VeLivePlayerResolutionOrigin;
playStreamMain.streamType = VeLivePlayerStreamTypeMain; // 流类型配置为主路

// 配置备流地址
VeLivePlayerStreamData.VeLivePlayerStream playStreamBackup = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamBackup.url = "https://pull.example.com/live/备.flv";
playStreamBackup.format = VeLivePlayerFormatFLV;
playStreamBackup.resolution = VeLivePlayerResolutionOrigin;
playStreamBackup.streamType = VeLivePlayerStreamTypeBackup; // 流类型配置为备路

// 创建播放源
VeLivePlayerStreamData streamData = new VeLivePlayerStreamData();

// 开启主备切换
streamData.enableMainBackupSwitch = true;

// 添加主流
streamData.mainStreamList = new ArrayList<>();
streamData.mainStreamList.add(playStreamMain);

// 添加备流
streamData.backupStreamList = new ArrayList<>();
streamData.backupStreamList.add(playStreamBackup);

// 配置播放源
mLivePlayer.setPlayStreamData(streamData);

// 开始播放
mLivePlayer.play();
  1. 当播放器内部发生主备切换时,会通过 VeLivePlayerObserver 的回调接口 onMainBackupSwitch 进行通知。代码示例如下所示。
public void onMainBackupSwitch(VeLivePlayer player, VeLivePlayerDef.VeLivePlayerStreamType streamType, VeLivePlayerError error) {
	// 主备切换回调通知
}

多档位切换

播放器支持配置多档位的直播拉流地址,通过接口可以实现多档位直播流的切换。

接入准备

获取源流和各档位转码流拉流地址。如您使用了火山引擎视频直播服务,请先登录控制台完成转码配置,再获取拉流地址,地址方法如下所示。

本文的接入说明以下列拉流地址为例。

档位拉流地址
源流(Orgin)https://pull.example.com/live/123456.flv
超清(UHD)https://pull.example.com/live/123456_uhd.flv
高清(HD)https://pull.example.com/live/123456_hd.flv
标清(SD)https://pull.example.com/live/123456_sd.flv
低清(LD)https://pull.example.com/live/123456_ld.flv

接入说明

  1. 配置多档位地址进行播放。代码示例如下所示。
// 配置多档位流地址
VeLivePlayerStreamData.VeLivePlayerStream playStreamOrgin = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamOrgin.url = "https://pull.example.com/live/123456.flv";
playStreamOrgin.format = VeLivePlayerFormatFLV;
playStreamOrgin.resolution = VeLivePlayerResolutionOrigin; // 原始档位
playStreamOrgin.streamType = VeLivePlayerStreamTypeMain;

VeLivePlayerStreamData.VeLivePlayerStream playStreamUHD = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamUHD.url = "https://pull.example.com/live/123456_uhd.flv";
playStreamUHD.format = VeLivePlayerFormatFLV;
playStreamUHD.resolution = VeLivePlayerResolutionUHD; // UHD 档位
playStreamUHD.streamType = VeLivePlayerStreamTypeMain;

VeLivePlayerStreamData.VeLivePlayerStream playStreamHD = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamHD.url = "https://pull.example.com/live/123456_hd.flv";
playStreamHD.format = VeLivePlayerFormatFLV;
playStreamHD.resolution = VeLivePlayerResolutionHD; // HD 档位
playStreamHD.streamType = VeLivePlayerStreamTypeMain;

VeLivePlayerStreamData.VeLivePlayerStream playStreamSD = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamSD.url = "https://pull.example.com/live/123456_sd.flv";
playStreamSD.format = VeLivePlayerFormatFLV;
playStreamSD.resolution = VeLivePlayerResolutionSD; // SD 档位
playStreamSD.streamType = VeLivePlayerStreamTypeMain;

VeLivePlayerStreamData.VeLivePlayerStream playStreamLD = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamLD.url = "https://pull.example.com/live/123456_ld.flv";
playStreamLD.format = VeLivePlayerFormatFLV;
playStreamLD.resolution = VeLivePlayerResolutionLD; // LD 档位
playStreamLD.streamType = VeLivePlayerStreamTypeMain;

// 创建播放源
VeLivePlayerStreamData streamData = new VeLivePlayerStreamData();

// 添加多档位流
streamData.mainStreamList = new ArrayList<>();
streamData.mainStreamList.add(playStreamOrgin);
streamData.mainStreamList.add(playStreamUHD);
streamData.mainStreamList.add(playStreamHD);
streamData.mainStreamList.add(playStreamSD);
streamData.mainStreamList.add(playStreamLD);

// 配置默认启播档位
streamData.defaultResolution = VeLivePlayerResolutionOrigin;

// 配置播放源
mLivePlayer.setPlayStreamData(streamData);

// 开始播放
mLivePlayer.play();

  1. 通过调用播放器的 switchResolution 接口可以实现多个档位之间的手动切换。代码示例如下所示。
mLivePlayer.switchResolution(VeLivePlayerResolutionUHD); // 切换到 UHD 档位

  1. 当档位切换成功时,会通过 VeLivePlayerObserver 的回调接口 onResolutionSwitch 进行回调。代码示例如下所示。
public void onResolutionSwitch(VeLivePlayer player, VeLivePlayerDef.VeLivePlayerResolution resolution, VeLivePlayerError error, VeLivePlayerDef.VeLivePlayerResolutionSwitchReason reason) {
	// 档位切换回调
}

自适应码率(ABR)拉流

自适应码率(Adaptive Bit-Rate,简称 ABR)是一种流媒体传输技术,通过一系列算法策略,动态切换不同档位媒体流,以达到适应网络带宽变化,防止观众在观看直播过程产生卡顿,提升播放质量和观看体验。

注意

ABR 功能只适用于 FLV 格式流。

接入准备

获取源流和各档位转码流拉流地址。如您使用了火山引擎视频直播服务,请先登录控制台完成转码配置,再获取拉流地址,地址方法如下所示。

本文的接入说明以下列拉流地址为例。

档位说明拉流地址码率(kbps)
源流(Orgin)https://pull.example.com/live/123456.flv2500
超清(UHD)https://pull.example.com/live/123456_uhd.flv2500
高清(HD)https://pull.example.com/live/123456_hd.flv1000
标清(SD)https://pull.example.com/live/123456_sd.flv800
低清(LD)https://pull.example.com/live/123456_ld.flv500

注意

ABR 功能需要配置多档位拉流地址时,SDK 中每个档位的编码码率需要与转码配置时填写的编码码率一致,配置方法可参考转码配置文档。

接入说明

  1. 配置多档位地址进行播放。代码示例如下所示。
// 配置多档位流地址
VeLivePlayerStreamData.VeLivePlayerStream playStreamOrgin = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamOrgin.url = "https://pull.example.com/live/123456.flv";
playStreamOrgin.format = VeLivePlayerFormatFLV;
playStreamOrgin.resolution = VeLivePlayerResolutionOrigin; // 原始档位
playStreamOrgin.streamType = VeLivePlayerStreamTypeMain;
playStreamOrgin.bitrate = 2500;

VeLivePlayerStreamData.VeLivePlayerStream playStreamUHD = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamUHD.url = "https://pull.example.com/live/123456_uhd.flv";
playStreamUHD.format = VeLivePlayerFormatFLV;
playStreamUHD.resolution = VeLivePlayerResolutionUHD; // UHD 档位
playStreamUHD.streamType = VeLivePlayerStreamTypeMain;
playStreamUHD.bitrate = 2500;

VeLivePlayerStreamData.VeLivePlayerStream playStreamHD = new VeLivePlayerStreamData.VeLivePlayerStream();
 playStreamHD.url = "https://pull.example.com/live/123456_hd.flv";
playStreamHD.format = VeLivePlayerFormatFLV;
playStreamHD.resolution = VeLivePlayerResolutionHD; // HD 档位
playStreamHD.streamType = VeLivePlayerStreamTypeMain;
playStreamHD.bitrate = 1000;

VeLivePlayerStreamData.VeLivePlayerStream playStreamSD = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamSD.url = "https://pull.example.com/live/123456_sd.flv";
playStreamSD.format = VeLivePlayerFormatFLV;
playStreamSD.resolution = VeLivePlayerResolutionSD; // SD 档位
playStreamSD.streamType = VeLivePlayerStreamTypeMain;
playStreamSD.bitrate = 800;

VeLivePlayerStreamData.VeLivePlayerStream playStreamLD = new VeLivePlayerStreamData.VeLivePlayerStream();
playStreamLD.url = "https://pull.example.com/live/123456_ld.flv";
playStreamLD.format = VeLivePlayerFormatFLV;
playStreamLD.resolution = VeLivePlayerResolutionLD; // LD 档位
playStreamLD.streamType = VeLivePlayerStreamTypeMain;
playStreamLD.bitrate = 500;

// 创建播放源
VeLivePlayerStreamData streamData = new VeLivePlayerStreamData();

// 添加多档位流
streamData.mainStreamList = new ArrayList<>();
streamData.mainStreamList.add(playStreamOrgin);
streamData.mainStreamList.add(playStreamUHD);
streamData.mainStreamList.add(playStreamHD);
streamData.mainStreamList.add(playStreamSD);
streamData.mainStreamList.add(playStreamLD);

// 配置默认启播档位
streamData.defaultResolution = VeLivePlayerResolutionOrigin;

// 开启 ABR
streamData.enableABR = true;

// 配置播放源
mLivePlayer.setPlayStreamData(streamData);

// 开始播放
mLivePlayer.play();

  1. ABR 档位自动切换时,会通过 VeLivePlayerObserver 的接口 onResolutionSwitch 进行回调。代码示例如下所示。
public void onResolutionSwitch(VeLivePlayer player, VeLivePlayerDef.VeLivePlayerResolution resolution, VeLivePlayerError error, VeLivePlayerDef.VeLivePlayerResolutionSwitchReason reason) {
	// 档位切换回调
}

截图

截图功能允许您在播放器中截取当前直播画面并生成一张图片。

接入说明

  1. 通过调用播放器的 snapshot 接口可以实现截图功能。截图仅在播放器播放成功后可以生效。代码示例如下所示。
int result = mLivePlayer.snapshot();
  1. 截图成功后,会通过播放器 VeLivePlayerObserver 的回调接口 onSnapshotComplete 进行回调,同时将截取的图片数据传递给回调方法。代码示例如下所示。
public void onSnapshotComplete(VeLivePlayer player, Bitmap bitmap) {
	// 截图成功回调,参数 bitmap 为截图的图片数据
}

SEI

SEI(Supplemental Enhancement Information)是直播流中的附加信息,它可以用于传递自定义的数据或元数据。

接入说明

  1. 在调用 play 方法之前,您可以通过配置播放器的 enableSei 属性来开启 SEI 信息的接收功能。代码示例如下所示。
// 创建播放器初始化配置
VeLivePlayerConfiguration config = new VeLivePlayerConfiguration();

// 打开 SEI 开关
 config.enableSei = true;
        
// 初始化配置
mLivePlayer.setConfig(config);
  1. 当直播流中有 SEI 信息时,播放器会通过 VeLivePlayerObserver 的回调接口 onReceiveSeiMessage 进行回调,并将接收到的 SEI 信息传递给回调方法。代码示例如下所示。
public void onReceiveSeiMessage(VeLivePlayer player, String message) 
	// SEI 回调
}

订阅视频数据

通过订阅解码后的视频数据,您可以获取视频帧数据并进行自定义的处理和渲染操作。播放器支持多种视频帧数据的回调,并提供了相应的参数和格式选项。

接入准备

视频帧像素格式和视频数据封装格式的枚举和含义如下表所示。

格式类型枚举说明

视频帧像素格式
VeLivePlayerPixelFormat

VeLivePlayerPixelFormatRGBA32

RGBA32

VeLivePlayerPixelFormatTexture2D 纹理

视频数据封装格式
VeLivePlayerVideoBufferType

VeLivePlayerVideoBufferTypeByteBuffer

ByteBuffer

VeLivePlayerVideoBufferTypeByteArrayByteArray
VeLivePlayerVideoBufferTypeTexture纹理

配置订阅视频数据前,请您根据需要选择格式组合。格式组合需要遵循下表中提供的 VeLivePlayerPixelFormat 和 VeLivePlayerVideoBufferType 的对应关系。

像素格式/封装格式VeLivePlayerPixelFormatRGBA32VeLivePlayerPixelFormatTexture
VeLivePlayerVideoBufferTypeByteBuffer×
VeLivePlayerVideoBufferTypeByteArray×
VeLivePlayerVideoBufferTypeTexture×√(性能最优)

接入说明

1.您可以调用播放器的 enableVideoFrameObserver 接口开启或关闭视频帧数据订阅功能。接口参数说明如下表所示。

参数类型说明
enableboolean是否开启视频帧回调。
pixelFormatVeLivePlayerPixelFormat视频帧像素格式。
bufferTypeVeLivePlayerVideoBufferType视频数据封装格式。

代码示例如下所示。

// 
mLivePlayer.enableVideoFrameObserver(true, VeLivePlayerPixelFormatRGBA32, VeLivePlayerVideoBufferTypeByteBuffer);
  1. 解码后的视频帧数据会通过播放器 VeLivePlayerObserver 的回调接口 onRenderVideoFrame 进行回调。代码示例如下所示。
public void onRenderVideoFrame(VeLivePlayer player, VeLivePlayerVideoFrame videoFrame) {
	// 视频帧数据回调
}

VeLivePlayerVideoFrame 参数说明如下表所示。

参数类型说明
bufferTypeVeLivePlayerVideoBufferType视频帧数据封装格式
pixelFormatVeLivePlayerPixelFormat视频帧像素格式
widthint视频帧的宽度,单位为 px
heightint视频帧的高度,单位为 px
ptslong视频帧的渲染时间戳,单位为 ms
textureVeLivePlayerVideoTexture当 bufferType 为 VeLivePlayerVideoBufferTypeTexture 时的视频数据,承载用于 OpenGL 渲染的纹理数据
bufferByteBuffer当 bufferType 为 VeLivePlayerVideoBufferTypeByteBuffer 时的视频数据,承载用于 JNI 层的 Direct Buffer
databyte[]当 bufferType 为 VeLivePlayerVideoBufferTypeByteArray 时的视频数据,承载用于 Java 层的字节数组数据

订阅音频数据

通过订阅解码后的音频数据,您可以获取音频帧数据并进行自定义的处理和渲染操作。

播放器支持音频帧数据帧回调格式为 PCM Float32 类型,数据封装格式为 ByteArray。

VeLivePlayerAudioBufferType音频数据封装格式
VeLivePlayerAudioBufferTypeByteArrayByteArray

接入说明

  1. 您可以调用播放器的 enableAudioFrameObserver 接口开启或关闭音频帧数据订阅功能。接口参数说明如下表所示。
参数类型说明
enableboolean是否开启音频帧回调。
enableRenderingboolean是否开启播放器渲染。当不需要播放器内部进行音频播放时,可以将该参数值配置为 false 。

代码示例如下所示。

// 订阅音频帧数据,打开播放器内部音频渲染
mLivePlayer.enableAudioFrameObserver(true, true);
  1. 解码后的音频帧数据会通过播放器 VeLivePlayerObserver 的 onRenderAudioFrame 接口进行回调。代码示例如下所示。
void onRenderAudioFrame(VeLivePlayer player, VeLivePlayerAudioFrame audioFrame) {
	// 音频帧数据回调
}

VeLivePlayerAudioFrame 参数说明如下表所示。

参数数据类型说明
bufferTypeVeLivePlayerAudioBufferType音频帧数据封装格式
sampleRateint音频采样率,单位为 Hz
channelsint声道数
bitDepthint音频位深度
ptslong音频渲染时间戳,单位为 ms
bufferbyte[]PCM 音频数据
samplesint音频采样点个数

拉流超分

超分,即超分辨率技术(Super-Resolution, SR)是指从观测到的低分辨率图像重建出相应的高分辨率图像的过程,移动端实时超分,是指利用算法技术在端上对低分辨率的帧进行实时重建,产生高分辨率的帧显示在屏幕上,从而改善视频内容的细节与对比度,全面提升视频的播放清晰度和观看体验的优化手段。

接入说明

  1. 联系技术支持开通拉流超分功能。
  2. 调用播放器的 setEnableSuperResolution(boolean enable) 方法开启或者关闭拉流超分功能,默认状态为关闭。
参数类型说明
enableboolean是否开启超分功能。
  1. 开启失败后,会通过 VeLivePlayerObserver 中的 onStreamFailedOpenSuperResolution 进行回调。代理方法签名如下所示。
void onStreamFailedOpenSuperResolution(VeLivePlayer player, VeLivePlayerError error);

如果开启超分失败,可能有以下几种原因。

  • 流的实际分辨率大于超分支持的最高分辨率。
  • 流的帧率大于超分支持的最高帧率。
  • 当前机型不支持超分。

域名解析

直播拉流 SDK 支持调用火山引擎 HTTPDNS 服务对拉流地址的预解析,以此来降低播放首帧时长。

接入说明

  1. 开通云解析 DNS 服务

  2. 登录移动解析 HTTPDNS 控制台

  3. 左侧导航栏选择实例信息,记录您的鉴权密钥,包含 SERVICE ID 和 SECRET KEY。

  4. 在拉流客户端调用 setVeHttpDNSAuth 方法配置调用 HTTPDNS 服务需要使用的鉴权密钥,代码示例如下所示。

    VeLiveCommon.setVeHttpDNSAuth(getApplicationContext(), "http_dns_serviceID", "http_dns_key")
    
  5. 调用 prefetchDomains 方法进行域名解析,解析成功后的 IP 地址会自动设置给播放器,代码示例如下所示。

    List<String> domains = new ArrayList<String>();
    domains.add("xxx.pull.com");
    domains.add("yyy.pull.com");
    VeLiveCommon.prefetchDomains(domains);