本文为您介绍如何使用 Android 播放器 SDK 的基础功能。
TTVideoEngine 提供了类似于 Android 系统 MediaPlayer 的播放控制的方法。
调用 play 方法开始或恢复播放视频:
ttVideoEngine.play(); // 开始播放或恢复播放
调用 pause 方法暂停播放视频。再次调用 play 方法,状态可由暂停恢复到播放。示例代码如下:
ttVideoEngine.pause(); // 暂停播放 ttVideoEngine.play(); // 播放器由暂停恢复到播放状态
在调用 play 前通过 setStartTime 方法指定开始播放时间点,用于实现从指定时间开始播放或跳过片头等功能。示例代码如下:
注意
如果您使用预渲染功能,需在 prepare 前设置起播时间。
int startPlayPositionMS = 1000; // 单位 MS ttVideoEngine.setStartTime(startPlayPositionMS); // 从 1 秒钟起播 ttVideoEngine.play();
调用 play 后,通过 seekTo 方法 Seek 到指定位置进行播放,实现拖拽进度条到指定时间开始播放的功能。示例代码如下:
/** 演示 seek 到 1 秒的位置 */ ttVideoEngine.seekTo(1000, new SeekCompletionListener() { @Override public void onCompletion(boolean success) { // seek 操作完成后回调。success 参数标识本次 seek 是否成功。true:成功 } }); ttVideoEngine.setVideoEngineInfoListener(new VideoEngineInfoListener() { @Override public void onVideoEngineInfos(VideoEngineInfos videoEngineInfos) { if (TextUtils.equals(videoEngineInfos.getKey(), VideoEngineInfos.USING_RENDER_SEEK_COMPLETE)) { // seek 渲染完成回调。 } } });
调用 stop 方法停止播放视频:
ttVideoEngine.stop(); // 停止播放
说明
暂停播放和停止播放的区别在于:暂停播放后,调用 play 会恢复播放;停止播放后,调用 play 会重新起播。
调用 releaseAsync 方法异步释放播放器实例:
ttVideoEngine.releaseAsync(); // 异步释放播放器实例 boolean isReleased = ttVideoEngine.isReleased(); //获取释放状态 ttVideoEngine = null; // 防止再次调用
说明
TTVideoEngine 设置为 null,防止再次调用。播放器 SDK 支持在播放视频时,只解码音频而不解码视频,适用于纯音频播放场景。相比您根据自身业务逻辑实现的纯音频播放,SDK 只解码音频会更省电。
注意
该功能仅高级版支持。请确保您已购买高级版的 License,详见播放器 License。
// 开启纯音频播放 ttVideoEngine.setRadioMode(true); // 恢复音视频播放 ttVideoEngine.setRadioMode(false);
SDK 支持 BASH(经火山引擎优化的升级版 DASH 协议)视频流的播放。播放前需开启以下 option:
ttVideoEngine.setIntOption(TTVideoEngineInterface.PLAYER_OPTION_ENABLE_DASH, 1); ttVideoEngine.setIntOption(TTVideoEngineInterface.PLAYER_OPTION_ENABLE_BASH, 1);
初始化播放器后,调用 play 前,通过 setIntOption 开启 Texture Render。示例代码如下:
ttvideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_USE_TEXTURE_RENDER, 1);
Android 播放器 SDK 支持填充、旋转和镜像等显示设置。
视频的比例和播放控件的比例不一致,就会造成视频拉伸变形的问题。你可以通过设置 displayMode 和 disPlayView 的参数来设置不同的显示模式。
注意
若采用此方案,disPlayView 的父布局必须采用 FrameLayout。
// 无变形;等比例缩放;画面不被裁剪;可能有黑边 int displayMode1 = TTVideoEngineInterface.IMAGE_LAYOUT_ASPECT_FIT; // 可能会变形;画面宽高都充满控件;画面不被裁剪;无黑边 int displayMode2 = TTVideoEngineInterface.IMAGE_LAYOUT_TO_FILL; // 无变形;等比例缩放;画面可能被裁剪;无黑边 int displayMode3 = TTVideoEngineInterface.IMAGE_LAYOUT_ASPECT_FILL; // 无变形;画面宽充满控件,高按视频比例适配;画面可能被裁剪;可能有黑边。 int displayMode4 = TTVideoEngineInterface.IMAGE_LAYOUT_ASPECT_FILL_X; // 无变形;画面高充满控件,宽按视频比例适配;画面可能被裁剪;可能有黑边。 int displayMode5 = TTVideoEngineInterface.IMAGE_LAYOUT_ASPECT_FILL_Y; // 即使开启 texturerender,也使用调整 View 尺寸 ttvideoEngine.setUseEngineDisplayMode(true); View disPlayView = findViewById(R.id.textureView); // View disPlayView = findViewById(R.id.surfaceView); // 参数 disPlayView 传入显示画面的 TextureView 或 SurfaceView ttvideoEngine.setDisplayMode(disPlayView, displayMode1);
横竖屏切换等视图尺寸变化时
// 横竖屏切换等 View 尺寸变化时,需在系统回调 onSizeChanged 里再次触发 View 尺寸调整。 protected void onSizeChanged(int w, int h, int oldw, int oldh) { ttvideoEngine.setDisplayMode(disPlayView, displayMode1); }
注意
若采用此方案,必须开启 Texture Render。
// 无变形;等比例缩放;画面不被裁剪;可能有黑边 int displayMode1 = TTVideoEngineInterface.IMAGE_LAYOUT_ASPECT_FIT; // 可能会变形;画面宽高都充满控件;画面不被裁剪;无黑边 int displayMode2 = TTVideoEngineInterface.IMAGE_LAYOUT_TO_FILL; // 无变形;等比例缩放;画面可能被裁剪;无黑边 int displayMode3 = TTVideoEngineInterface.IMAGE_LAYOUT_ASPECT_FILL; ttvideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_USE_TEXTURE_RENDER, 1); ttvideoEngine.setIntOption(TTVideoEngineInterface.PLAYER_OPTION_IS_RENDER_WHEN_SIZE_CHANGE, 1); View disPlayView = findViewById(R.id.textureView); // View disPlayView = findViewById(R.id.surfaceView); // 参数 disPlayView 传入显示画面的 TextureView 或 SurfaceView ttvideoEngine.setDisplayMode(disPlayView, displayMode1);
横竖屏切换等视图尺寸变化时
// 横竖屏切换等 View 尺寸变化时,需在系统回调 onSizeChanged 里再次触发纹理尺寸修改。 protected void onSizeChanged(int w, int h, int oldw, int oldh) { ttvideoEngine.forceDraw(); }
按照以下步骤实现旋转功能:
play 前,开启 Texture Render。play 后,调用 setRotation 设置视频显示时的旋转角度。设置后,视频会顺时针旋转。示例代码如下:int rotation = 90; // 旋转角度仅支持 0°/90°/180°/270°,其他值无效 ttvideoEngine.setRotation(rotation); // 设置视频显示时的旋转角度,在调用 `play` 后设置
调用 setMirrorHorizontal 和 setMirrorVertical 方法设置水平和垂直镜像。
// 设置水平镜像 boolean mirrorHorizontal = true; ttVideoEngine.setMirrorHorizontal(mirrorHorizontal);// 开启水平镜像 ttVideoEngine.setMirrorHorizontal(!mirrorHorizontal);// 关闭水平镜像 // 设置垂直镜像 boolean mirrorVertical = true; ttVideoEngine.setMirrorVertical(mirrorVertical);// 开启垂直镜像 ttVideoEngine.setMirrorVertical(!mirrorVertical);// 关闭垂直镜像
在 TTVideoEngine 触发 onPrepared 回调之后,调用 getVideoWidth 和 getVideoHeight 方法获取视频的宽高:
int videoWidth = ttVideoEngine.getVideoWidth(); //获取视频的宽 int videoHeight = ttVideoEngine.getVideoHeight(); // 获取视频的高
play 前,开启 Texture Render。play 后,通过 snapshot 设置截图回调通知;调用 SnapshotListener 接口中定义的 onSnapShot 方法,通过回调函数来获取并处理视频截图位图、截图的宽度和高度。示例代码如下:mVideoEngine.snapshot(new SnapshotListener() { @Override public void onSnapShot(final Bitmap bitmap, final int with, final int height) { } });
Android 播放器 SDK 支持获取当前播放进度、视频时长和缓存进度等信息。
调用 getCurrentPlaybackTime 方法获取当前播放位置:
说明
建议该方法的调用时间间隔 >= 200 ms。
// 获取当前播放位置,单位 MS int currentPostion = ttVideoEngine.getCurrentPlaybackTime();
通过 onCurrentPlaybackTimeUpdate 回调获取定时进度:
// 通过设置进度回调间隔开启回调,play 之前设置 ttVideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_POSITION_UPDATE_INTERVAL, 200); ttVideoEngine.setVideoEngineCallback(new VideoEngineCallback() { // ...省略其余实现方法 @Override public void onCurrentPlaybackTimeUpdate(TTVideoEngine engine, int currentPlaybackTime) { Log.v("VideoPlay", "onCurrentPlaybackTimeUpdate " + engine + " " + currentPlaybackTime); } });
在 TTVideoEngine 触发 onPrepared 回调之后,调用 getDuration 方法获取当前播放视频总时长。示例代码如下:
// 获取视频时长,单位 MS int duration = ttVideoEngine.getDuration();
调用 getLoadedProgress 方法获取缓存进度。示例代码如下:
// 获取缓存进度,取值 1-100 int loadedProgress = ttVideoEngine.getLoadedProgress();
通过 onBufferingUpdate 回调获取缓存进度。示例代码如下:
ttVideoEngine.setListener(new VideoEngineListener() { // ...省略其余实现方法 @Override public void onBufferingUpdate(TTVideoEngine engine, int percent) { Log.v("VideoPlay", "onBufferingUpdate " + engine + " " + percent); // 缓存进度回调,可用于展示播放进度条上的二级缓存进度,取值 1-100 } });
调用 setLooping 方法并取值为 true 开启循环播放:
ttVideoEngine.setLooping(true); // 开启循环播放 ttVideoEngine.setLooping(false); // 关闭循环播放 boolean isLooping = ttVideoEngine.isLooping(); // 查询是否开启循环播放
调用 setPlaybackParams 方法设置倍速。默认值为 1,取值范围为 (0,3]。示例代码如下:
PlaybackParams params = new PlaybackParams(); params.setSpeed(1f); // 默认为 1 倍速,取值范围(0, 3] ttVideoEngine.setPlaybackParams(params);
若需要播放倍速大于 3,需开启高倍速开关
// 请在 play/prepare 前设置 ttVideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_PLAY_SPEED_EXTEND, 1);
Android 播放器 SDK 支持音频焦点、调节音量和静音等音量设置的功能。
调用 setIsMute 方法并取值为 true 实现静音。示例代码如下:
ttVideoEngine.setIsMute(true); // 静音 boolean isMute = ttVideoEngine.isMute(); // 获取是否静音
调节音量包含调节系统音量、调节播放音量方式。
setVolume 方法设置系统左右声道音量。示例代码如下:float maxVolume = ttVideoEngine.getMaxVolume(); // 获取最大音量 float currentVolume = ttVideoEngine.getVolume(); // 获取当前音量 ttVideoEngine.setVolume(1f, 1f); // 设置左右声道音量,取值范围为 [0,maxVolume]
播放器 SDK 内部不处理音频焦点,需接入方需监听 AudioManager.OnAudioFocusChangeListener 来处理音频焦点的获取和释放。参考官方文档:管理音频焦点。
Vid 模式下播放视频时,视频点播服务会下发多个清晰度的播放地址。播放器 SDK 通过 Resolution 枚举(详见清晰度枚举参考)来统一管理所有清晰度档位。
在播放器成功获取视频信息后(即 onFetchedVideoInfo 回调触发后),可调用 supportedResolutionTypes() 方法获取当前视频支持的所有清晰度档位。
Resolution[] supportedResolutions; ttVideoEngine.setVideoInfoListener(new VideoInfoListener() { @Override public boolean onFetchedVideoInfo(VideoModel videoModel) { if (videoModel != null) { // 获取清晰度数组,用于在 UI 上构建清晰度选择列表 supportedResolutions = ttVideoEngine.supportedResolutionTypes(); } return false; } });
在播放过程中的任何时刻,您都可以调用 getCurrentResolution() 获取当前正在播放的实际清晰度。
调用 getCurrentResolution 获取当前清晰度:
Resolution currentResolution = ttVideoEngine.getCurrentResolution();
无论是设置起播清晰度,还是在播放中进行切换,都是通过调用 configResolution 方法实现。
在 onFetchedVideoInfo 回调中,您可以根据业务逻辑(例如,优先使用用户上次的选择,或使用默认值)来设置初始播放的清晰度。
// 在 onFetchedVideoInfo 回调中设置起播 @Override public boolean onFetchedVideoInfo(VideoModel videoModel) { // 假设我们希望以 360p 起播 Resolution defaultResolution = Resolution.Standard; // 由于播放源不一定包含 360p,调用 findDefaultResolution 找到最接近的一个可用清晰度 Resolution startResolution = TTVideoEngine.findDefaultResolution(videoModel, defaultResolution); if (startResolution != null) { ttVideoEngine.configResolution(startResolution); } return false; }
当用户在 UI 界面上选择了一个新的清晰度时,直接调用 configResolution 即可。
// 假设用户从 UI 上点击了 resolutions 列表中的第 i 项 Resolution selectedResolution = supportedResolutions[i]; // 直接调用接口切换 ttVideoEngine.configResolution(selectedResolution); // 监听切换结果 ttVideoEngine.setVideoEngineCallback(new VideoEngineCallback() { @Override public void onVideoStreamBitrateChanged(Resolution newResolution, int bitrate) { // 清晰度切换成功 Log.d("VideoPlay", "Switched to " + newResolution); } @Override public void onError(Error error) { // 如果切换失败,可能会收到相关错误回调 } });
清晰度平滑切换(或称无缝切换)是指播放器在不同清晰度之间切换时,画面过渡平滑、无黑屏、无明显卡顿的技术。该功能依赖于视频源本身是帧对齐的。对于火山引擎视频点播服务转码生成的 MP4 和 HLS 视频,默认已实现帧对齐。
注意
如需了解如何转码生成帧对齐视频以及在 DirectUrl 模式下开启平滑切换功能,可提交工单联系火山引擎技术支持。
以下示例代码演示如何在 Vid 模式下开启平滑切换:
// 开启 HLS 平滑切换的核心开关 ttVideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_HLS_SEAMLESS_SWITCH, 1); // 建议同时开启,以获得最佳的 Master M3U8 解析和调度性能 ttVideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_MASTER_M3U8_OPTIMIZE, 1); // MP4 播放源平滑切换 ttVideoEngine.setIntOption(PLAYER_OPTION_SEGMENT_FORMAT_FLAG, (1 << SEGMENT_FORMAT_FMP4) | (1 << SEGMENT_FORMAT_MP4)); ttVideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_BASH, 1); ttVideoEngine.setVideoEngineCallback(new VideoEngineCallback() { /** * 当码率(清晰度)发生变化时回调 * @param resolution 切换后的清晰度枚举 * @param bitrate 切换后的码率 */ @Override public void onVideoStreamBitrateChanged(Resolution resolution, int bitrate) { Log.d("VideoPlay", "Stream switched successfully to: " + resolution + ", bitrate: " + bitrate); } });
如果您通过 DirectUrl 方式播放 HLS 视频,在设置播放源和预加载时均可以通过 urlExpiredTimes 参数设置过期时间。
设置播放源:在设置 DirectUrl 播放源时,创建 StrategySource 时传入过期时间,然后调用 setStrategySource 播放。示例代码如下所示:
StrategySource directUrlSource = new DirectUrlSource.Builder() .setVid(vid) .addItem(new DirectUrlSource.UrlItem.Builder() .setUrl(url) .setCacheKey(cacheKey) .setUrlExpires(new String[]{"xxx"}) // 单位为秒 .build()) .build(); mEngine.setStrategySource(directUrlSource);
预加载:在预加载播放场景下,您可在创建 DirectUrlSource 时,通过 setUrlExpires 传入过期时间,然后按照预加载流程调用 addTask 进行预加载。示例代码如下所示:
DirectUrlSource directUrlSource = new DirectUrlSource.Builder() .setVid(vid) .addItem(new DirectUrlSource.UrlItem.Builder() .setUrl(url) .setCacheKey(cacheKey) .setUrlExpires(new String[]{"xxx"}) // 单位为秒 .build()) .build(); PreloaderURLItem preloaderUrlItem = mFactory.createUrlItem(directUrlSource, preloadSize); preloaderUrlItem.setCallBackListener(new PreloadCallback(vid, this)); TTVideoEngine.addTask(preloaderUrlItem);
判断过期时间是否设置成功:可通过 Debug 调试状态下查看日志,确认播放地址中是否包含 hlsproxyQuery 关键字。示例如下:
hlsproxyQuery=expirteTime%03Dxxxxxxxxxx
在实现客户端播放逻辑前,请确保已满足以下服务端配置:
FileType:与播放普通视频的关键不同在于,您的应用服务端在调用 GetPlayInfo 接口获取播放地址或签发 PlayAuthToken 时,必须将 FileType 参数设置为 standard_evideo(加密视频)或 standard_eaudio(加密音频)。在确保已满足上述服务端要求后,您可以根据播放方式和是否开启 HLS 加密改写,参考以下客户端实现。
在此场景下,客户端的播放代码与播放普通 Vid 视频完全相同,SDK 内部会自动处理解密流程。若您开启了 HLS 标准加密改写功能,需要额外设置 UrlExtendParams 参数传入鉴权参数 AppAuthToken。
说明
若您开启 HLS 标准加密改写功能,在播放、下载和预加载的全链路中,都可以通过 urlExtendParams 参数传递 AppAuthToken:
VidPlayAuthTokenSource.Builder 中通过 setUrlExtendParams() 方法设置。DownloadVidTask 对象上通过 setUrlExtendParams() 方法设置。PreloaderVidItem 对象上通过 setUrlExtendParams() 方法设置。VidPlayAuthTokenSource 实例也必须设置 urlExtendParams 属性。策略会读取此属性并将其应用到内部创建的预加载任务中。// 1. (按需配置) 准备您的鉴权参数 Map // 如果开启了“HLS 标准加密改写”,请创建并填充此 Map。 // Map<String, String> authParams = new HashMap<>(); // authParams.put("AppAuthToken", "<your_token>"); // 2. 构造 Vid 播放源 VidPlayAuthTokenSource.Builder builder = new VidPlayAuthTokenSource.Builder() .setVid("your_hls_encrypted_vid") .setPlayAuthToken("your_play_auth_token"); // 3. (按需配置) 将鉴权参数设置给播放源 // 如果开启了“HLS 标准加密改写”,则执行此步骤。 // SDK 会自动将 Map 中的键值对转换为 URL 查询参数拼接到 M3U8 请求中。 // builder.setUrlExtendParams(authParams); // 4. 构建播放源并播放 StrategySource vidSource = builder.build(); ttVideoEngine.setStrategySource(vidSource); ttVideoEngine.play();
业务类型(tag)用于区分同一应用(appid)内不同类型的音视频。可以根据业务需要按视频场景、视频时长等划分,比如沉浸式 feed 流、短视频视频、长视频等。调用 setTag 方法设置业务类型,代码示例如下所示。
ttVideoEngine.setTag("tag"); // 设置 Tag
子业务类型(subtag)用于区分同一业务类型下更为细分的音视频类型,比如加密视频、非加密视频、音频等。调用 setSubTag 方法设置子业务类型,代码示例如下所示。
ttVideoEngine.setSubTag("subtag"); //设置 SubTag
调用 View#setKeepScreenOn(boolean) 设置屏幕保持常亮,View#getKeepScreenOn 获取是否保持常亮。示例代码如下所示。
textureView.setKeepScreenOn(true); // 设置屏幕保持常亮 boolean isKeepScreenOn = textureView.getKeepScreenOn(); // 是否保持屏幕常亮
您可以通过设置 VideoEngineCallback 来监听播放器在整个生命周期中的各种状态和事件。设置监听的示例代码:
ttVideoEngine.setVideoEngineCallback(new VideoEngineCallback() { @Override public void onPlaybackStateChanged(TTVideoEngine engine, int playbackState) { Log.v("VideoPlay", "onPlaybackStateChanged " + engine + " " + playbackState); // 播放状态改变回调 switch (playbackState) { case TTVideoEngine.PLAYBACK_STATE_PLAYING: // 开始播放 break; case TTVideoEngine.PLAYBACK_STATE_ERROR: // 播放出错 // Note: // 1.本消息不代表本次播放失败,内部重试后可能会恢复播放 // 2.若最终播放失败,会在 VideoEngineListener#onError() 中回调 break; case TTVideoEngine.PLAYBACK_STATE_STOPPED: // 播放停止 break; case TTVideoEngine.PLAYBACK_STATE_PAUSED: // 播放暂停 break; default: break; } } @Override public void onLoadStateChanged(TTVideoEngine engine, int loadState) { Log.v("VideoPlay", "onLoadStateChanged " + engine + " " + loadState); switch (loadState) { case TTVideoEngine.LOAD_STATE_PLAYABLE: // buffer end or renderStart break; case TTVideoEngine.LOAD_STATE_STALLED: // buffer start break; case TTVideoEngine.LOAD_STATE_ERROR: // load error break; default: break; } } @Override public void onVideoSizeChanged(TTVideoEngine engine, int width, int height) { Log.v("VideoPlay", "onVideoSizeChanged " + engine + " " + width + " " + height); // 播放器解析到视频宽高变化时回调 // 对于像素比不是 1:1 的视频而言,width/height 不是最终渲染的宽高比 // 最终渲染的宽高比需要结合 onSARChanged 回调中的 num 和 den 计算 // displayAspectRatio = (num/(float)den) * (width/(float)height) } @Override public void onBufferingUpdate(TTVideoEngine engine, int percent) { Log.v("VideoPlay", "onBufferingUpdate " + engine + " " + percent); // 缓存进度回调,可用于展示播放进度条上的二级缓存进度 } @Override public void onPrepare(TTVideoEngine engine) { Log.v("VideoPlay", "onPrepare " + engine); // prepare 时立刻回调 } @Override public void onPrepared(TTVideoEngine engine) { Log.v("VideoPlay", "onPrepared " + engine + " isSystem " + engine.isSystemPlayer()); // prepare 完成后回调 } @Override public void onRenderStart(TTVideoEngine engine) { Log.v("VideoPlay", "onRenderStart " + engine); // 开始渲染时回调,可以认为此刻视频画面已经展示 } @Override public void onStreamChanged(TTVideoEngine engine, int type) { Log.v("VideoPlay", "onStreamChanged " + engine + " " + type); // 音视频流变化通知 // type 枚举:TTVideoEngine.VIDEO_STREAM/TTVideoEngine.AUDIO_STREAM } @Override public void onCompletion(TTVideoEngine engine) { Log.v("VideoPlay", "onCompletion " + engine); // 播放完成回调 } @Override public void onError(Error error) { Log.v("VideoPlay", "onError " + error); // 播放失败回调 // 错误码文档:https://www.volcengine.com/docs/4/66441/ //播放失败后,内部会自动释放播放器 } /** * 卡顿开始回调 * * @param code 类型: * {@link VideoBufferDetailListener#BUFFERING_TYPE_NET} 网络卡顿 * {@link VideoBufferDetailListener##BUFFERING_TYPE_DECODER} 解码卡顿 * * @param afterFirstFrame 卡顿发生时机: * {@link VideoBufferDetailListener#BEFORE_FIRST_FRAME} 首帧前卡顿 * {@link VideoBufferDetailListener#AFTER_FIRST_FRAME} 首帧后卡顿 * * @param action 造成卡顿的 action: * {@link VideoBufferDetailListener#BUFFER_START_ACTION_NONE} 正常播放过程中卡顿 * {@link VideoBufferDetailListener#BUFFER_START_ACTION_SEEK} seek * {@link VideoBufferDetailListener#BUFFER_START_ACTION_CHANG_RESOLUTION} 切换分辨率 */ @Override public void onBufferStart(int code, int afterFirstFrame, int action) { Log.v("VideoPlay", "onBufferStart " + code + ", " + afterFirstFrame + ", " + action); // buffer 开始,展示 loading } /** * 视频加载进度百分比回调 * @param percent 缓冲进度百分比(0-99) */ public void onBufferPercentUpdate(int percent) { // 更新加载进度,percent 加载进度 } /** * 卡顿结束回调 * @param code * {@link VideoBufferDetailListener#BUFFERING_TYPE_NET} 网络卡顿 * {@link VideoBufferDetailListener##BUFFERING_TYPE_DECODER} 解码卡顿 */ @Override public void onBufferEnd(int code) { Log.v("VideoPlay", "onBufferEnd " + code); // buffer 结束,隐藏 loading } @Override public void onSARChanged(int num, int den) { Log.v("VideoPlay", "onSARChanged " + num + ", " + den); // 视频 sample aspect ratio 回调,用于控制显示模式 float sampleAspectRatio = num / (float) den; } });
播放器 SDK 支持回调当前视频一段时间内获取的视频数据大小,可用来在视频的起播、Seek、卡顿等情况下展示当前视频下载速度。实现的步骤和示例代码如下所示。
注意
该功能仅高级版支持。请确保您已购买高级版的 License,详见播放器 License。
在初始化 SDK 前全局开启实时下载速度监听。
// 全局开启实时下载速度监听,在初始化 SDK 前调用 TTVideoEngine.setIntValue(DATALOADER_KEY_INT_NEED_SPEED_TEST_BY_TIMEINTERNAL, 1); // 初始化 SDK Env.start(...);
设置单个实例测速时间间隔。
// value 为测速时间间隔,单位 MS 推荐值 500 MS // 调用时机:设置播放源后调用 ttVideoEngine.setCustomHeader("X-SpeedTest-TimeInternal", "500");
设置回调监听。
// 设置回调监听 TTVideoEngine.setDataLoaderListener(new DataLoaderListener()); interface DataLoaderListener { ... /** * * @param what == DATALOADER_KEY_NOTIFY_SPEEDINFO 时为网速回调 * 此时: * code 为 netReadLen(单位 Byte) * parameter 为 netReadTime(单位 ms) * info 字段无需关注 */ public void onNotify(int what, long code, long parameter, String info) { if (what == DataLoaderHelper.DATALOADER_KEY_NOTIFY_SPEEDINFO) { float dataSize = code / 1024; float time = (float) (parameter / 1000.0); float speed = dataSize / time; // 单位 KB/s Log.d(TAG, "download speed = " + speed); } } }
调用 clearAllCaches 方法清除视频缓存:
TTVideoEngine.clearAllCaches(true); // true 清除所有缓存;false LRU 保留最近 10 条缓存。
在播放过程中,如果用户拖动进度条将视频快进到视频总时长 3 秒以内的位置,播放器会直接回调播放完成。如果您需要支持 Seek 到最后一帧,可通过如下方法配置:
mVideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_SEEK_LASTFRAME,1); mVideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_SEEK_END,1);
为提升播放的稳定性和可靠性,播放器 SDK 提供 DirectUrl 模式的主备地址容灾功能。您可以设置一个主播放地址和一个备用播放地址。当主播放地址播放失败(如 DNS 解析失败、连接超时、收到 4xx/5xx 响应等)时,播放器内部会自动尝试切换到备用地址进行播放。
注意
1.35.1 及以上版本支持该功能。
在初始化前开启 DATALOADER_KEY_INT_ALLOW_TRY_THE_LAST_URL。
// 在 SDK 初始化之前,开启主备地址容灾的全局开关 TTVideoEngine.setIntValue(DataLoaderHelper.DATALOADER_KEY_INT_ALLOW_TRY_THE_LAST_URL, 1); // 初始化 SDK Env.start(/* 省略 */);
构造包含主备地址的播放源:
注意
您提供的主地址和备用地址,都必须指向内容完全相同的视频文件。如果文件内容不一致,可能导致切换后出现播放花屏、进度错乱等异常。
final String vid = "video id"; // 视频源与 vid 必须一一对应 final String mainUrl = "http://www.example.com/h264.mp4"; // 主 URL final String backUpUrl = "http://www.examplebackup.com/h264.mp4"; // 备 URL // cacheKey 建议用 url 中不变的不分的 md5,比如 path 部分的 md5 final String cacheKey = TTVideoEngine.computeMD5(mainUrl); StrategySource directUrlSource = new DirectUrlSource.Builder() .setVid(vid) .addItem(new DirectUrlSource.UrlItem.Builder() .setUrls(new String[]{mainUrl, backUpUrl}) .setCacheKey(cacheKey) .build()) .build();
当播放发生错误时,播放器将尝试重新播放,直到达到最大重试次数。如果所有重试均失败,最终会触发 onError 回调。自 1.50.2.8 版本起,您可以通过 setIntOption 方法并设置 PLAYER_OPTION_MAX_ERROR_COUNT 的值来配置当前播放失败后的最大重试次数。如果未进行设置,播放器默认最多重试 3 次。
// 设置当前播放失败后最大重试次数为 3 次 ttVideoEngine.setIntOption(TTVideoEngine.PLAYER_OPTION_MAX_ERROR_COUNT, 3);
默认情况下,播放器 SDK 会自动生成唯一的设备 ID,您可在质量平台追查该设备 ID 的播放记录。参考以下代码获取设备 ID:
// 获取设备 ID TTVideoEngine.getDeviceID()
说明
如果您自己已有一套独立的用户 ID 体系,希望通过用户 ID 来追查单个用户的单次播放行为,则可自定义用户 ID。
支持设置 SDK 的网络超时时间,推荐 10 秒。示例如下:
// 1. 打开全局开关,启用网络超时检测功能 // 设置 ALGO_OPTION_USE_ENGINE_NETWORK_TIMEOUT 为 1 TTVideoEngine.setIntValue(TTVideoEngine.ALGO_OPTION_USE_ENGINE_NETWORK_TIMEOUT, 1); TTVideoEngine ttVideoEngine = new TTVideoEngine(context, TTVideoEngine.PLAYER_TYPE_OWN); // 2. 为 engine 实例设置网络超时时间(秒) // 本示例设置为 10 秒 ttVideoEngine.setIntOption(PLAYER_NETWORK_TIMEOUT, 10); // 3. 关闭建连报错重试。在建立连接失败时,不进行重试 ttVideoEngine.setIntOption(PLAYER_OPTION_SET_ORIGINAL_RETRY, 0); // 4. 关闭 engine 层播放失败重试。播放失败时,不进行重试 ttVideoEngine.setIntOption(PLAYER_OPTION_SET_MAX_ACCUMULATED_COUNT, 0);
UnionInfo 是播放端从设备中提取的用于标识访问或设备唯一性的信息。播放器 SDK 通过 UnionInfo 向应用服务端发起播放请求,应用服务端通过服务端 SDK 本地签发包含 UnionInfo 的 PlayAuthToken 并下发给播放器 SDK,即可播放火山引擎私有加密视频。更多信息,请见火山引擎私有加密方案。您可通过以下代码生成 UnionInfo:
String unionInfo = TTVideoEngine.getEngineUniqueId(context);
Resolution 枚举如下表所示。
key | 视频清晰度 | 音频清晰度 | 视频描述 | 音频描述 |
|---|---|---|---|---|
Standard | 360p | medium | 标清 | 普通音质 |
High | 480p | higher | 高清 | 高音质 |
SuperHigh | 720p | highest | 超清 | 音乐音质 |
ExtremelyHigh | 1080p | original | 1080P | 原画 |
TwoK | 2k | 无 | 2K | 此档位对音频不生效 |
FourK | 4k | 无 | 4K | 此档位对音频不生效 |
Auto | 自动调节 | 无 | DASH 支持根据网速动态调节分辨率 | 此档位对音频不生效 |