基础能力使用
基础能力使用
在 快速开始 中,我们完成了qplayer2播放器的创建\播放\销毁,本文介绍如何使用qplayer2的播放能力
播放
创建播放数据
let builder : QMediaModelBuilder = new QMediaModelBuilder()
builder.addStreamElement("",QPlayerUrlType.QAUDIO_AND_VIDEO,1080,"你的地址",true,"","")
let model : QMediaModel = builder.build(false)
addStreamElements 属性说明
属性名 | 属性说明 |
---|---|
userType | 用户自定义Type,目前预留,可以填空字符串 |
url | 资源地址 |
urlType | 媒体的资源属性 只包含视频/只包含音频/同时有视频音频 |
quality | 清晰度 |
isSelected | 是否起播时播放该流 |
backupUrl | 备用地址 |
referer | http/https 协议的地址 支持该属性 |
hlsDrmKey | 私有DRM解密的key,用在私有hls加密视频播放的场景中 |
mp4DrmKey | mp4 drm 的解密 key 用于 CENC-AES-CTR 加密的视频播放场景中 |
mp4QNDrmComKey | mp4 七牛私有 drm 的解密 comkey 用于七牛私有 mp4 加密的视频播放场景中 |
mp4QNDrmFileKey | mp4 七牛私有 drm 的解密 filekey 用于七牛私有 mp4 加密的视频播放场景中 |
视频URL类型枚举
export enum QPlayerUrlType {
QAUDIO_AND_VIDEO = 0, //音视频
QAUDIO = 1, //纯音频
QVIDEO = 2, //纯视频
NONE = 3, //无
}
播放媒体资源
/*** 播放音视频资源
* @param model 音视频资源
*/
this.mPlayerContext.get_control_handler().playMediaModel(model,0)
播放错误监听
当视频起播时,如果遇到网络等问题原因,导致没有和服务器建立链接,那么会导致视频播放失败,总共会有3次重试机会,3次都失败的情况下会回调onOpenFailed方法。
当视频已经起播后,在中途遇到网络等问题原因,进入buffer, 那么内核会一直重试,直到再次连接上服务端继续播放,或者用户通过接口停止播放该视频,在重试的过程中 onReconnectStart / onReconnectEnd 会被回调,那么可以监控回调的次数来做业务层的结束播放的策略,当然在正常播放的情况下,这两个方法也是会被回调的,所以最好结合buffer的回调数据一起使用。
private mMediaNetworkListener : QIPlayerMediaNetworkListener = {
/***
开始重连
@param context 当前的播放器
@param userType 重连url流的userType
@param urlType 重连url流的urlType
@param url 重连的url
@param retryTime 已重试的次数
*/
onReconnectStart:(context : QIPlayerContext , userType: string , urlType: QPlayerUrlType , url: string , retryTime: number ) => {
},
/***
重连结束
@param context 当前的播放器
@param userType 重连url流的userType
@param urlType 重连url流的urlType
@param url 重连的url
@param retryTime 已重试的次数
@param error 错误码
*/
onReconnectEnd:(context : QIPlayerContext , userType: string , urlType: QPlayerUrlType , url: string , retryTime: number , error: QPlayerOpenError ) => {
},
/***
打开失败
@param context 当前的播放器
@param userType 重连url流的userType
@param urlType 重连url流的urlType
@param url 重连的url
@param error 错误码
*/
onOpenFailed:(context : QIPlayerContext , userType: string , urlType: QPlayerUrlType , url: string , error: QPlayerOpenError ) => {
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerMediaNetworkListener(this.mMediaNetworkListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerMediaNetworkListener(this.mMediaNetworkListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerMediaNetworkListener()
播放错误码枚举
export enum QPlayerOpenError{
UNKNOW = 10000,
NONE = 0,
IOERROR = -5,
INTERRUPT = -1414092869,
URL_INVALID = -875574520,
FORMAT_INVALID = -1094995529
}
暂停播放
this.mPlayerContext.get_control_handler().pauseRender()
恢复播放
this.mPlayerContext.get_control_handler().resumeRender()
停止当前视频播放
this.mPlayerContext.get_control_handler().stop()
播放 drm 视频
mp4 加密
目前 QPlayer2 支持七牛私有加密以及显式的 CENC-AES-CTR 加密,暂不支持隐式加密。CENC-AES-CTR 的初始化向量(IV) 由加密工具随机生成并存储在加密后的 MP4 文件中,QPlayer2 读取 MP4 文件的 IV 和QmediaModel 存储的 mp4DrmKey 进行解密
对 MP4 文件进行七牛私有加密方式播放
let builder : QMediaModelBuilder = new QMediaModelBuilder()
builder.addStreamElementWithMp4QNDrm("",QPlayerUrlType.QAUDIO_AND_VIDEO,1080,"你的地址",true,"","","mp4QNDrmComKey","mp4QNDrmFileKey")
let model : QMediaModel = builder.build(false)
this.mPlayerContext.get_control_handler().playMediaModel(model,0)
对 MP4 文件进行 CENC-AES-CTR 加密
可以选择 ffmpeg 对一个 MP4 进行加密。加密命令如下:
ffmpeg -i test2.mp4 -vcodec copy -acodec copy -encryption_scheme cenc-aes-ctr -encryption_key c7e16c4403654b85847037383f0c2db3 -encryption_kid a7e61c373e219033c21091fa607bf3b8 encrypted_IV_test.mp4
命令说明
test2.mp4 为输入文件
encrypted_IV_test.mp4 为输出文件
-vcodec copy 和 -acodec copy :指定视频流和音频流的编码方式为原始流的拷贝,即不进行重新编码,保持与原始文件相同的编码格式。
-encryption_scheme cenc-aes-ctr :设置加密方案为 CENC-AES-CTR,即采用 CTR 模式进行加密。
-encryption_key c7e16c4403654b85847037383f0c2db3 指定加密所使用的密钥,即解密所使用的 key。这里的c7e16c4403654b85847037383f0c2db3 是一个示例密钥,您可以替换为您自己的密钥,格式要求为:16字节的16进制数据。
-encryption_kid a7e61c373e219033c21091fa607bf3b8:指定加密所使用的密钥标识符(KID)。这里的 a7e61c373e219033c21091fa607bf3b8 是一个示例 KID,您可以替换为您自己的密钥标识符, 格式要求为:16字节的16进制数据。
加密后可通过ffplay 4.4 版本进行播放验证,播放正常即可。命令如下:
ffplay encrypted_IV_test.mp4 -decryption_key c7e16c4403654b85847037383f0c2db3
QPlayer2 对加密后 MP4 文件进行播放
let builder : QMediaModelBuilder = new QMediaModelBuilder()
builder.addStreamElementWithMp4Drm("",QPlayerUrlType.QAUDIO_AND_VIDEO,1080,"你的地址",true,"","","mp4DrmKey")
let model : QMediaModel = builder.build(false)
this.mPlayerContext.get_control_handler().playMediaModel(model,0)
HLS 加密
let builder : QMediaModelBuilder = new QMediaModelBuilder()
builder.addStreamElementWithHlsDrm("",QPlayerUrlType.QAUDIO_AND_VIDEO,1080,"你的地址",true,"","","hlsDrmKey")
let model : QMediaModel = builder.build(false)
this.mPlayerContext.get_control_handler().playMediaModel(model,0)
鉴权
鉴权功能介绍见 鉴权相关文档
鉴权监听
private mAuthenticationListener : QIPlayerAuthenticationListener = {
/**
@brief 鉴权失败回调
@param context 当前播放器
@param error 失败错误码
*/
onAuthenticationFailed:(context: QIPlayerContext, error:QPlayerAuthenticationErrorType)=>{
this.addToastView(`鉴权失败:${error.valueOf()}`)
},
/**
@brief 鉴权成功回调
@param context 当前播放器
*/
onAuthenticationSuccess:(context: QIPlayerContext)=>{
this.addToastView("鉴权成功")
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerAuthenticationListener(this.mAuthenticationListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerAuthenticationListener(this.mAuthenticationListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerAuthenticationListener()
鉴权错误码枚举
/**
鉴权不通过错误码
*/
export enum QPlayerAuthenticationErrorType {
NONE, //鉴权出错
NO_BASE_AUTH, //缺少基础功能权限
NO_VR_AUTH, //缺少VR功能权限
NO_BLIND_AUTH, //缺少色盲功能权限
NO_SEI_AUTH, //缺少SEI功能权限
NO_SRT_AUTH, //缺少SRT功能权限
NO_APM_AUTH //缺少APM功能权限
};
视频解码方式
目前支持的解码方式有:软解、硬解、自动,一般情况下,使用自动,内核会根据手机的硬件情况,要播放的视频资源编码格式等信息,挑选合适的解码方式进行解码,各个解码方式的优劣情况如下
软解: 解码较慢,但是兼容性好,适用于所有手机
硬解:解码性能高,但是有一定兼容性,比如某些视频资源的编码格式,硬解芯片不支持。并且相对于软解,首帧的速度慢。
设置优先选择哪种解码方式
设置完成后下一次播放生效.
最终的解码方式可能不是设置的,在设置的解码方式不能正确解码时,内核会进行降级,选择其他能正确解码的方式
this.mPlayerContext.get_control_handler().setDecoderType(QPlayerDecoderPriority.AUTO)
优先选择的解码方式枚举
该枚举主要用于设置解码方式
typedef NS_ENUM(NSInteger, QPlayerDecoder) {
export enum QPlayerDecoderPriority {
AUTO = 0, //自动
HARDWARE_PRIORITY = 1, //硬解优先
SOFT_PRIORITY = 2, //软解优先
}
};
播放器视频解码监听相关
private mDecoderTypeListener : QIPlayerVideoDecodeListener = {
/**
当前视频用的是哪种解码方式
@param context 当前的播放器
@param type 解码方式
*/
onVideoDecodeByType:(context : QIPlayerContext , type: QPlayerDecoderType) =>{
}
/**
* 通知当前视频解码失败,
* @param retry 底层是重试
*/
onDecodeFailed:(context : QIPlayerContext , retry: boolean) => {
}
/**
如果当前视频编码 所在设备或者sdk不支持 则回调该方法
@param context 当前的播放器
@param codecId 视频的编码id
*/
onNotSupportCodecFormat:(context : QIPlayerContext , codec: number) => {
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerVideoDecodeTypeListener(this.mDecoderTypeListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayeVideoDecodeTypeListener(this.mDecoderTypeListener)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerVideoDecodeTypeListener()
解码方式枚举
该枚举主要用于监听返回的解码方式
export enum QPlayerDecoderType{
NONE = 0, //无
SOFTWARE = 1, //软解
HARDWARE = 30, //硬解
}
切换视频进度
参数为要定位的position 单位毫秒
this.mPlayerContext.get_control_handler().seek(1000)
设置起播方式
下一次播放生效
this.mPlayerContext.get_control_handler().setSeekMode(QPlayerSeek.NORMAL)
seek方式枚举
export enum QPlayerSeek {
NORMAL = 0, //关键帧
ACCURATE = 1, //精准
}
seek 状态监听
一般情况下 seek都会成功,如果网络差的情况下,会无限loading(除非调用stop才会停止),直到seek到指定的位置为止。但是如果视频源本身是格式不正确的,比如pts错乱等问题,才会导致seek失败,所以在seek失败回调中,做好提示工作就好,不要尝试再次seek
private mSeekListener : QIPlayerSeekListener = {
/**
seek成功回调
@param context 当前的播放器
*/
onSeekSuccess:(context : QIPlayerContext) => {
},
/**
seek失败回调
@param context 当前的播放器
*/
onSeekFailed:(context : QIPlayerContext) => {
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerSeekListener(this.mSeekListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerSeekListener(this.mSeekListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerSeekListener()
获取当前播放状态
this.mPlayerContext.get_control_handler().currentPlayerState
获取视频时长
this.mPlayerContext.get_control_handler().duration
获取当前进度
this.mPlayerContext.get_control_handler().currentPosition
获取当前下载速度
this.mPlayerContext.get_control_handler().downloadSpeed
获取当前缓冲进度
this.mPlayerContext.get_control_handler().bufferPostion
播放器状态
在整个播放器实例生命周期中,播放会在不同的状态中切换,用户可以通过监听播放器状态,实现上层业务逻辑,
比如在视频播放完时,展示其他视频的推荐页,那么只需监听播放器状态回调,待回调的状态是COMPLETED,则展示推荐页
播放器状态枚举
export enum QPlayerState {
NONE = 0, //初始状态 0
INIT = 1, //播放器开始创建各种对象 没有对应的state 创建完对象就上报这个状态 1
PREPARE = 2, //开始拉视频数据解码变换等,重新换地址后,都走这个状态 2
PLAYING = 4, //播放中 4
PAUSED_RENDER = 6, //暂停渲染 6
COMPLETED = 7, //播放完成 7
SEEKING = 8, //SEEK 8
STOPPED = 9, //停止当前播放的视频 9
MISTAKE = 10, //播放出错 是否需要分 可恢复 和 不可恢复 10
END = 11, //播放器释放各种对象完成 11
MEDIA_ITEM_PREPARE = 12, //开始拉视频数据解码变换等,重新换地址后,都走这个状态 针对Media Item的play 方式 12
RELEASE = 13 //播放器结束,且释放各类资源 13
}
播放器状态变更监听相关
private mStateChangeListener : QIPlayerStateChangeListener ={
/**
状态变更回调
@param context 当前的播放器
@param state 播放器状态
*/
onStateChange:(context : QIPlayerContext ,state: QPlayerState)=>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerStateListener(this.mStateChangeListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerStateListener(this.mStateChangeListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerStateListener()
播放速度
播放速度的调整范围建议在0.25-2.0之间,这样会有一个比较好的效果
设置播放速度
参数为倍速值
this.mPlayerContext.get_control_handler().setSpeed(0.5)
获取当前播放速度
this.mPlayerContext.get_control_handler().playerSpeed
速度变更监听相关
private mPlaySpeed : QIPlayerSpeedListener = {
/**
倍速改变回调
@param context 当前的播放器
@param speed 改变后的倍速
*/
onSpeedChanged:(context : QIPlayerContext, speed:number)=>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerSpeedChangeListener(this.mPlaySpeed)
//移除监听
this.mPlayerContext.get_control_handler().removePlayeSpeedChangeListener(this.mPlaySpeed)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerSpeedChangeListener()
清晰度
QPlayer2提供的清晰度能力是无缝切换清晰度方案,在切换过程中,画面是连续的画面,不会出现类似跳帧的情况。
使用无缝切换清晰度功能,必须在mediaModel中配置多路清晰度,如果使用非immediately方式(即异步方式)时,同时只能有一次切换会话存在,会话结束后,才能切下一次
切换视频清晰度
//使用该方法时,mediaModel中需要存在多个StreamElement
/**
切换清晰度
@param userType 切换清晰度的url流的userType
@param urlType 切换清晰度的url流的 urlType
@param quality 要切到哪路清晰度
@param immediately true 立即切换 用于直播流,false 无缝切换,切换过程是一个异步过程,用于点播流
@return true 调用成功, false 调用失败
*/
this.mPlayerContext.get_control_handler().switchQuality("",QPlayerUrlType.QAUDIO_AND_VIDEO,1080,false)
获取当前的清晰度
//使用该方法时,mediaModel中需要存在多个StreamElement,返回清晰度数值标记
/**
获取指定 userType urlType 的清晰度
@param userType 切换清晰度的url流的userType
@param urlType 切换清晰度的url流的 urlType
@return true 调用成功, false 调用失败
*/
this.mPlayerContext.get_control_handler().getCurrentQuality("",QPlayerUrlType.QAUDIO_AND_VIDEO)
获取当前正在切换的清晰度
/**
获取指定 userType urlType 流正在切换的清晰度(非immediately方式)
@param userType 切换清晰度的url流的userType
@param urlType 切换清晰度的url流的 urlType
@return true 调用成功, false 调用失败
*/
this.mPlayerContext.get_control_handler().getSwitchingQuality("",QPlayerUrlType.QAUDIO_AND_VIDEO)
播放器清晰度相关监听
private mQualityListener: QIPlayerQualityListener = {
/**
开始清晰度切换
@param context 当前的播放器
@param usertype 开始切换清晰度的url流的userType
@param urlType 开始切换清晰度的url流的
@param oldQuality 切换前的清晰度
@param newQuality 要切到哪路清晰度
*/
onQualitySwitchStart:(context : QIPlayerContext , usertype: string , urlType: QPlayerUrlType , oldQuality: number , newQuality: number ) =>{
}
/**
清晰度切换完成
@param context 当前的播放器
@param usertype 开始切换清晰度的url流的userType
@param urlType 开始切换清晰度的url流的
@param oldQuality 切换前的清晰度
@param newQuality 要切到哪路清晰度
*/
onQualitySwitchComplete:(context : QIPlayerContext , usertype: string , urlType: QPlayerUrlType , oldQuality: number , newQuality: number ) =>{
}
/**
清晰度切换取消
@param context 当前的播放器
@param usertype 开始切换清晰度的url流的userType
@param urlType 开始切换清晰度的url流的
@param oldQuality 切换前的清晰度
@param newQuality 要切到哪路清晰度
*/
onQualitySwitchCanceled:(context : QIPlayerContext , usertype: string , urlType: QPlayerUrlType , oldQuality: number , newQuality: number ) =>{
}
/**
清晰度切换失败
@param context 当前的播放器
@param usertype 开始切换清晰度的url流的userType
@param urlType 开始切换清晰度的url流的
@param oldQuality 切换前的清晰度
@param newQuality 要切到哪路清晰度
*/
onQualitySwitchFailed:(context : QIPlayerContext , usertype: string , urlType: QPlayerUrlType , oldQuality: number , newQuality: number ) =>{
}
/**
目前仅支持同时有一个清晰度切换,如果前一个还未切换完,再次发起切换 会回调这个函数
@param context 当前的播放器
@param usertype 开始切换清晰度的url流的userType
@param urlType 开始切换清晰度的url流的
*/
onQualitySwitchRetryLater:(context : QIPlayerContext , usertype: string , urlType: QPlayerUrlType ) =>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerQualityListener(this.mQualityListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerQualityListener(this.mQualityListener)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerQualityListener()
直播支持多路清晰度切换
无缝切换清晰度方案需要配置以下三个条件
- 首先切换的模式要选择立即切换即:immediately=true
- 服务端配置PTS透传,
- 对应的清晰度要做主动转码设置
如果无法满足以上3个条件,那么建议用最基础的能力来实现清晰度切换,即每个清晰度都是一个media model,切换时,调用playMediaModel来播放新的清晰度流。
视频宽高改变监听
在视频首帧渲染时,会调用该回调,告诉上层当前的视频宽高是多少,如果在这个这个视频播放的生命周期中,宽高改变,那么还会再次调用该回调.
private mVideoFrameSizeChangedListener : QIPlayerVideoFrameSizeChangeListener ={
/**
推流端视频长宽变化回调
@param context 当前的播放器
@param width 视频宽度
@param height 视频高度
*/
onVideoFrameSizeChanged:(context : QIPlayerContext, width: number, height:number ) =>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerVideoFrameSizeChangeListener(this.mVideoFrameSizeChangedListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerVideoFrameSizeChangeListener(this.mVideoFrameSizeChangedListener)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerVideoFrameSizeChangeListener()
播放进度监听
只有在点播的时候 duration 和 progress 才有意义,直播的话这两个值没有参考意义
private mProgressListener : QIPlayerProgressListener = {
/***
进度变更回调
@param context 当前的播放器
@param progress 当前进度 单位毫秒
@param duration 当前视频总时长 单位毫秒
*/
onProgressChanged:(context:QIPlayerContext, progress:number, duration:number) => {
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerProgressChangeListener(this.mProgressListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerProgressChangeListener(this.mProgressListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerProgressChangeListener()
实时帧率
获取当前fps
this.mPlayerContext.get_control_handler().fps
实时帧率监听
private mFPSListener : QIPlayerFPSListener = {
/**
@brief fps 改变的回调
@param context 当前的播放器
@param fps 帧率
*/
onFPSChanged:(context:QIPlayerContext, FPS:number)=>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerFPSChangeListener(this.mFPSListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerFPSChangeListener(this.mFPSListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerFPSChangeListener()
像素格式或者音频sample格式不支持的监听
private mFormatListener : QIPlayerFormatListener = {
/**
@brief 当前有format 不支持,所以视频没法播放
@param context 当前的播放器
*/
onFormatNotSupport:(context:QIPlayerContext)=>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerFormatListener(this.mFormatListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerFormatListener(this.mFormatListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerFormatListener()
缓冲拉流监听
private mDownloadListener : QIPlayerDownloadListener = {
/**
@brief 拉流速率改变
@param context 当前的播放器
@param downloadSpeed 速度 单位: b/s (比特每秒)
@param bufferPos 缓冲的进度
*/
onDownloadChanged:(context:QIPlayerContext, speed:number, bufferPos:number)=>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerDownloadChangeListener(this.mDownloadListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerDownloadChangeListener(this.mDownloadListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerDownloadChangeListener()
播放器操作不允许执行监听
在某些状态下,一些操作将不被执行,通过该监听回调上来通知
private mCommandNotAllowListener : QIPlayerCommandNotAllowListener = {
/**
@brief 操作不被允许回调
@param context 操作异常的播放器
@param commandName 操作名称
@param state 操作被检测时播放器的状态
*/
onCommandNotAllow:(context:QIPlayerContext, commandName:string, state:QPlayerState)=>{}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerCommandNotAllowListener(this.mCommandNotAllowListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerCommandNotAllowListener(this.mCommandNotAllowListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerCommandNotAllowListener()
buffering 监听
private mBufferingListener : QIPlayerBufferingListener = {
/**
@brief 开始buffering
@param context 当前播放器
*/
onBufferingStart:(context:QIPlayerContext)=>{
},
/**
@brief 结束buffering
@param context 当前播放器
*/
onBufferingEnd:(context: QIPlayerContext)=>{}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerBufferingChangeListener(this.mBufferingListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerBufferingChangeListener(this.mBufferingListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerBufferingChangeListener()
截图
调用截图接口,就会回调截图时的video画面,并以jpeg的格式返回
/**
截图
*/
this.mPlayerContext.get_control_handler().shootVideo()
截图图片类型枚举
/**
截图图片类型
*/
export enum QPlayerShootVideoType {
NONE = 0,
JPEG //jpeg格式
};
截图相关监听
private mShootVideoListener : QIPlayerShootVideoListener = {
/**
截图成功回调
@param context 当前的播放器
@param imageData 图片的 NSData 数据
@param width 图片的宽
@param height 图片的高
@param type 图片类型
*/
onShootSuccessful:(context : QIPlayerContext, imageData:Uint8Array, width:number, height:number, type: QPlayerShootVideoType) =>{
}
/**
截图失败回调
@param context 当前的播放器
*/
onShootFailed:(context : QIPlayerContext) =>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerShootVideoListener(this.mShootVideoListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerShootVideoListener(this.mShootVideoListener)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerShootVideoListener()
码率
获取当前码率
this.mPlayerContext.get_control_handler().biteRate
实时码率监听
private mBiteRateListener : QIPlayerBiteRateListener = {
/**
@brief 码率变换回调
@param context 当前播放器
@param bitrate 比特率, 单位:bps
*/
onBiteRateChanged:(context:QIPlayerContext, bitrate:number)=>{}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerBiteRateChangeListener(this.mBiteRateListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerBiteRateChangeListener(this.mBiteRateListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerBiteRateChangeListener()
SEI 数据回调
用户自定义数据可以带在H264或者H265的编码帧里,用于实现一些基于时间轴的业务场景。
开启该功能后,如果视频资源内带有SEI数据 会通过监听接口抛给业务层。
该功能需要单独开通,具体可以联系技术支持咨询。
开启 SEI
this.mPlayerContext.get_control_handler().setSEIEnable(true)
SEI 数据监听
private mSEIListener: QIPlayerSEIDataListener = {
/**
SEI 数据回调,且回调时机为SEI数据所在帧的时间
@param context 当前的播放器
@param data SEI 数据
*/
onSEIData:(context:QIPlayerContext, data:Uint8Array)=>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerSEIDataListener(this.mSEIListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerSEIDataListener(this.mSEIListener)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerSEIDataListener()
视频数据上抛
开启视频数据上抛
this.mPlayerContext.get_control_handler().setVideoDataEnable(true)
设置视频回调数据类型
this.mPlayerContext.get_control_handler().setVideoDataType(QVideoType.RGBA)
视频回调数据类型枚举
export enum QVideoType {
YUV_420P = 1,
NV12 = 2,
RGBA = 3
};
视频数据上抛相关监听
private mVideoDataListener : QIPlayerVideoDataListener = {
onVideoData:(context : QIPlayerContext, width: number, height: number, videoType: QVideoType, buffer: Uint8Array) => {
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerVideoDataListener(this.mVideoDataListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerVideoDataListener(this.mVideoDataListener)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerVideooDataListener()
音频数据上抛相关监听
开启音频数据上抛
this.mPlayerContext.get_control_handler().setAudioDataEnable(true)
音频数据上抛相关监听
private mAudioDataListener : QIPlayerAudioDataListener = {
onAudioData:(context : QIPlayerContext, sampleRate: number, format:QSampleFormat, channelNum: number, channelLayout: QChannelLayout, data:Uint8Array)=>{
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerAudioDataListener(this.mAudioDataListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerAudioDataListener(this.mAudioDataListener)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerAudioDataListener()
渲染相关监听
private mRenderListener : QIPlayerRenderListener = {
/**
首帧耗时回调
@param context 当前的播放器
@param elapsedTime 从play 开始到首帧渲染出来的总耗时 单位毫秒
*/
onFirstFrameRendered:(context : QIPlayerContext, elapsedTime:number) => {
}
}
//添加监听
this.mPlayerContext.get_render_handler().addPlayerRenderListener(this.mRenderListener)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerRenderListener(this.mRenderListener)
//移除全部监听
this.mPlayerContext.get_control_handler().removeAllPlayerRenderListener()
设置视频渲染比例
this.mPlayerContext.get_render_handler().setRenderRatio(QRenderRatio.AUTO)
视频比例枚举
export enum QRenderRatio {
AUTO = 1,
FULL_SCREEN, //铺满
STRETCH, //拉伸
Ratio_16_9, //16:9
Ratio_4_3, //4:3
}
设置视频缩放比例
/***
* 设置画面缩放
* @param scale 缩放倍数
* @return true 设置成功 false 设置失败
*/
this.mPlayerContext.get_render_handler().setScale(0.2)
设置视频镜像类型
/***
* 设置镜像
* @param type 镜像类型
* @return true 设置成功 false 设置失败
*/
this.mPlayerContext.get_render_handler().setMirrorType(QPlayerMirror.MIRROR_NONE)
镜像枚举
export declare enum QPlayerMirror {
MIRROR_NONE = 0,
MIRROR_X = 1,
MIRROR_Y = 2,
MIRROR_X_Y = 3
}
设置视频旋转
/***
* 设置旋转
* @param angle 旋转角度(0<=angle<=360)
* @return true 设置成功 false 设置失败
*/
this.mPlayerContext.get_render_handler().setRotation(180)
设置色觉优化
this.mPlayerContext.get_render_handler().setBlindType(QBlindType.NONE)
色觉优化枚举
export enum QBlindType {
NONE = 0, //无
RED = 1, //红色盲
GREEN = 2, //绿色盲
BLUE = 3, //蓝色盲
}
VR视频播放
在播放VR视频时,需要在mediaModel中配置vr视频的资源 并且将streamElement的QPlayerRenderType设置为PANORAMA_EQUIRECT_ANGULAR
然后通过设置vr视频视角改变视频朝向
该功能需要单独开通,具体可以联系技术支持咨询。
/***
* 设置VR视频的旋转角度
* @param rotateX 横向角度 (360度制)
* @param rotateY 纵向角度 (360度制)
* @return true 设置成功 false 设置失败
*/
this.mPlayerContext.get_render_handler().setPanoramaViewRotate(0,0)
视频类型枚举
export enum QVideoRenderType {
NONE = -1,
PLANE = 0,
PANORAMA_EQUIRECT_ANGULAR = 1,
}
后台播放
后台播放除了 QPlayer2 设置以外,还需要申请鸿蒙的长时任务和音频后台播放。同时还在 module.json 中需要申请后台播放权限
设置是否支持后台播放
/**
*设置是否后台播放
* @param enable yes后台播放,no后台播放暂停
*/
this.mPlayerContext.get_control_handler().setBackgroundPlayEnable(true)
鸿蒙长时任务和音频后台播放
async createSession() {
let type: AVSessionManager.AVSessionType = 'audio';
let session = await AVSessionManager.createAVSession(this.context,'SESSION_NAME', type);
// 激活接口要在元数据、控制命令注册完成之后再执行
await session.activate();
console.info(`session create done : sessionId : ${session.sessionId}`);
}
onBackground() {
// Ability has back to background
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
this.createSession()
let wantAgentInfo : wantAgent.WantAgentInfo = {
wants: [
{
bundleName: "com.qiniu.qplayer2demo",
abilityName: "EntryAbility"
}
],
// 点击通知后,动作类型
operationType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
// 点击通知后,动作执行属性
wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
};
wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj : WantAgent) => {
hilog.info(0x0000, 'testTag', '%{public}s', 'getWantAgent');
backgroundTaskManager.startBackgroundRunning(this.context,
backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK, wantAgentObj).then(() => {
console.info("Operation startBackgroundRunning succeeded");
}).catch((err: BusinessError) => {
console.error("Operation startBackgroundRunning failed Cause: " + err);
});
});
}
后台播放权限申请
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
}
字幕
字幕数据设置
let builder : QMediaModelBuilder = new QMediaModelBuilder()
builder.addStreamElement("",QPlayerUrlType.QAUDIO_AND_VIDEO,1080,"你的地址",true,"","")
builder.addSubtitleElement("中文","你的地址",true)
let model = builder.build(false)
设置是否开启字幕
/**
*设置是否开启字幕
* @param enable yes开启,no关闭
*/
this.mPlayerContext.get_control_handler().setSubtitleEnable(true)
设置字幕名称
/**
*设置字幕
* @param name 设置为名称为 name 的字幕。
*/
this.mPlayerContext.get_control_handler().setSubtitleEnable(true)
字幕监听
private mSubtitleCallBack : QIPlayerSubtitleListener = {
/**
字幕文本更改监听
@param context 当前的播放器
@param text 字幕文本
*/
onSubtitleTextChange:(context : QIPlayerContext , text: string ) => {
},
/**
字幕名称更改监听
@param context 当前的播放器
@param name 字幕名称 key
*/
onSubtitleNameChange:(context : QIPlayerContext , name: string ) => {
},
/**
字幕状态监听
@param context 当前的播放器
@param enable yes当前字幕状态关开启,no当前字幕状态关闭
*/
onSubtitleEnable:(context : QIPlayerContext , enable: boolean ) => {
},
/**
字幕加载状态监听
@param context 当前的播放器
@param name 字幕名称
@param result yes 加载成功,no 加载失败
*/
onSubtitleLoaded:(context : QIPlayerContext , name: string , result: boolean ) => {
},
/**
字幕解码状态监听
@param context 当前的播放器
@param name 字幕名称
@param result yes 加载成功,no 加载失败
*/
onSubtitleDecoded:(context : QIPlayerContext , name: string , result: boolean ) => {
}
}
//添加监听
this.mPlayerContext.get_control_handler().addPlayerSubtitleListener(this.mSubtitleCallBack)
//移除监听
this.mPlayerContext.get_control_handler().removePlayerSubtitleListener(this.mSubtitleCallBack)
//移除所有监听
this.mPlayerContext.get_control_handler().removeAllPlayerSubtitleListener()