# 说明

有用到过视频播放的地方,由于一个 mp4 文件受限于网络等多种原因,播放效果不一定好。了解到有开源的播放器,能实现类似视频网站的自适应分辨率的功能,这里使用的是 Google 的 Shaka Player

# 使用 Shaka player

# 下载 JS 库

release 页面,下载 JS 库。
打开压缩包,在 package/dist 目录下,即可找到 Shaka player 所需的 JS 文件。

  • shaka-player.compiled.js 播放器 SDK
  • shaka-player.ui.js 带 UI 的播放器 SDK
  • controls.css 播放器 UI css 文件

为了使用其自带的播放器 UI ,这里使用 shaka-player.ui.js 。另外 Shaka player 还不支持 hls 的播放,所以需要另外引入 mux.js

<script src="shaka/mux.min.js"></script>
<script src="shaka/shaka-player.ui.js"></script>
<link rel="stylesheet" type="text/css" href="shaka/controls.css">

# 初始化使用

Shaka player 通过 video 标签初始化,先添加 video 标签:

<video data-shaka-player id="video" style="width:100%;height:100%" 
    autoplay x5-video-player-type="h5" x5-video-player-fullscreen="true"
    playsinline="true"
    >
    <source src="vp9.mpd" />		
    <source src="h264.m3u8" />	
</video>

可直接在 video 标签中添加 source 来指定视频文件地址,当有多种格式的时候,Shaka player 会选择当前支持的格式播放。

初始化方法官方文档已给出了详细的示例

// 手动判断平台以加载不同的资源
/**
 
let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
        (navigator.platform.toUpperCase().indexOf('MAC')>=0)) &&
    !window.MSStream;
let manifestUri = "vp9.mpd";
if (isIOS) {
    manifestUri = "h264.m3u8";
}
*/
async function init() {
    // When using the UI, the player is made automatically by the UI object.
    const video = document.getElementById('video');
    const ui = video['ui'];
    const controls = ui.getControls();
    const player = controls.getPlayer();
    // Attach player and ui to the window to make it easy to access in the JS console.
    window.player = player;
    window.ui = ui;
    // Listen for error events.
    player.addEventListener('error', onPlayerErrorEvent);
    controls.addEventListener('error', onUIErrorEvent);
    // 配置播放器按钮
    const uiConfig = {
        'overflowMenuButtons' : ['quality', 'playback_rate', 'picture_in_picture', 'airplay', 'cast']
    };
    ui.configure(uiConfig);
    // 手动加载播放地址
    /** 
     
    try {
        await player.load(manifestUri);
        // This runs if the asynchronous load is successful.
        console.log('The video has now been loaded!');
    } catch (error) {
        onPlayerError(error);
    } 
    */
}
function onPlayerErrorEvent(errorEvent) {
    // Extract the shaka.util.Error object from the event.
    onPlayerError(event.detail);
}
function onPlayerError(error) {
    // Handle player error
    alert(error);
    console.error('Error code', error.code, 'object', error);
}
function onUIErrorEvent(errorEvent) {
    // Extract the shaka.util.Error object from the event.
    onPlayerError(event.detail);
}
function initFailed(errorEvent) {
    // Handle the failure to load; errorEvent.detail.reasonCode has a
    // shaka.ui.FailReasonCode describing why.
    console.error('Unable to load the UI library!');
}
// Listen to the custom shaka-ui-loaded event, to wait until the UI is loaded.
document.addEventListener('shaka-ui-loaded', init);
// Listen to the custom shaka-ui-load-failed event, in case Shaka Player fails
// to load (e.g. due to lack of browser support).
document.addEventListener('shaka-ui-load-failed', initFailed);
// 微信当中自动播放。非正常操作,不一定一直有效 (⊙o⊙)
if (typeof window.WeixinJSBridge !== 'undefined') {
    window.WeixinJSBridge.invoke('getNetworkType',{},function (e){
        // 利用该方法进行自动播放
        video.play();
    });
}

虽然使用了 Shaka player 播放视频,但对视频的播放控制并非由 Shaka player 提供,仍然使用 JS 中的 video 对象操作。

# 视频处理

Shaka player 默认支持的 vp9 编码的视频,在 Android 上支持还比较好,但在 iOS 中不能播放,所以在 iOS 中要使用 hls 播放。可以使用 ffmpeg 进行转码。

非专业 ffmpeg 用户,以下命令纯属复制,没有解释😄。

# 转 h264 编码以及不同分辨率

ffmpeg -y -i osc2.mp4 -c:v libx264 \
 -r 25 -x264opts 'keyint=48:min-keyint=48:no-scenecut' \
 -vf scale=-2:360 -b:v 560k -maxrate 560k \
 -movflags faststart -bufsize 8600k \
 -profile:v main -preset fast -an "h264_360p.mp4"

分辨率即 scale 参数设置的,如 1080p 则设为 scale=-2:1080 ,同时更高分辨率需要增大它的码率、比特率等,如:

ffmpeg -y -i osc2.mp4 -c:v libx264 \
 -r 25 -x264opts 'keyint=48:min-keyint=48:no-scenecut' \
 -vf scale=-2:1080 -b:v 4300k -maxrate 4300k \
 -movflags faststart -bufsize 8600k \
 -profile:v main -preset fast -an "h264_1080p.mp4"

# 转 vp9 编码

ffmpeg -i osc2.mp4 -c:v libvpx-vp9 -b:v 0 -crf 30 -pass 1 -an -f null /dev/null && \
ffmpeg -i osc2.mp4 -c:v libvpx-vp9 -vf scale=-2:720 -b:v 0 -crf 30 -pass 2 -c:a libopus vp9_720.webm

这里调整分辨率依旧是 scale 参数,不同的是质量是通过 -crf 来控制的。业余的理解:它执行了两次 ffmpeg 命令,第一次会生成一个信息文件,第二次会根据这个文件进行压缩转码,以获得更好的质量和更小的体积。降低 crf 以获得更高的视频质量。

# 提取音频

Shaka player 使用 mpd 或 m3u8 播放的时候,音频是作为一个单独的轨道的,因此需要提取出音频,再与视频打包。

ffmpeg -y -i osc2.mp4 -map 0:1 -vn -c:a aac -b:a 128k -ar 48000 -ac 2 audio.m4a

# 打包

使用 Shaka player 提供的 packager 进行打包,它将对多个视频文件进行切片并生成 mpd 或 m3u8 文件,即可加载到播放器当中使用。

mpd格式
packager \
  in=vp9_360.webm,stream=audio,init_segment='dash/audio_init.webm',segment_template='dash/audio_$Number%03d$.webm' \
  in=vp9_360.webm,stream=video,init_segment=dash/vp9_360_init.webm,segment_template='dash/vp9_360_$Number%03d$.webm' \
  in=vp9_720.webm,stream=video,init_segment=dash/vp9_720_init.webm,segment_template='dash/vp9_720_$Number%03d$.webm' \
  in=vp9_1080.webm,stream=video,init_segment=dash/vp9_1080_init.webm,segment_template='dash/vp9_1080_$Number%03d$.webm' \
  in=vp9_1440.webm,stream=video,init_segment=dash/vp9_1440_init.webm,segment_template='dash/vp9_1440_$Number%03d$.webm' \
  in=vp9_2160.webm,stream=video,init_segment=dash/vp9_2160_init.webm,segment_template='dash/vp9_2160_$Number%03d$.webm' \
  --segment_duration 3 \
  --generate_static_live_mpd \
  --mpd_output vp9.mpd
hls格式
packager \
  in=audio.m4a,stream=audio,init_segment=hls/audio_init.mp4,segment_template='hls/audio_$Number$.m4s' \
  in=h264_360p.mp4,stream=video,init_segment=hls/360p_init.mp4,segment_template='hls/360_$Number$.m4s' \
  in=h264_720p.mp4,stream=video,init_segment=hls/720p_init.mp4,segment_template='hls/720_$Number$.m4s' \
  in=h264_1080p.mp4,stream=video,init_segment=hls/1080p_init.mp4,segment_template='hls/1080_$Number$.m4s' \
  in=h264_1440p.mp4,stream=video,init_segment=hls/1440p_init.mp4,segment_template='hls/1440_$Number$.m4s' \
  in=h264_2160p.mp4,stream=video,init_segment=hls/2160p_init.mp4,segment_template='hls/2160_$Number$.m4s' \
  --hls_master_playlist_output h264.m3u8

其中第二行为音频文件,mpd 的可直接使用视频文件作为输入,它将自动提取音频。 hls 使用上面导出的音频文件。

执行完后将得到包含多个分辨率的 mpd 或 m3u8 文件,以及其视频切片。使用 Shaka player 播放,它将自动识别到不同的分辨率,可在按钮中选择,默认会根据网络加载合适的分辨率。

ffmpeg 功能强大,有众多的参数,因此也有许多不同的方式来转码视频,实现需要的效果。

~

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

HuaLin 微信支付

微信支付

HuaLin 支付宝

支付宝