目录
1.准备环境
1.1:下载FFmpeg
首先,打开FFmpeg的官方下载页面:https://ffmpeg.org/download.html
在里面找到:图标,点一下,在下面的列表中选择Windows builds from gyan.dev
点进去会跳转到这个页面,下拉找到release builds
,找到ffmpeg-release-essentials.zip
,点击下载并解压到一个你喜欢的地方。
1.2:配置环境变量
解压后,打开高级系统设置,选择环境变量。
在弹出的窗口里找到用户变量
,点击Path
,再点击下方的编辑(如图)。
先点击新建
,然后点击浏览
,选择你解压FFmpeg
的位置,在里边找到bin
这个文件夹(一定得是bin这个文件夹才行!),点击确定。
2.压制、准备视频
要实现画质切换,需要将视频压制成不同清晰度。
你可以用你最常用的压缩视频的方法进行压缩,这里不再赘述。
只是要注意一点,分辨率需要拥有:(以下仅供参考,以你实际为准)
2160P(4K)(可要可不要)
1080P
720P
480P
360P
2.1:生成m4a音频文件
下面,我们用FFmpeg生成音频文件。
首先,用cd命令进入你的视频目录,然后输入:
ffmpeg -i 你的视频文件名称(带后缀名)-vn -c copy audio.m4a
3. 使用 FFmpeg 生成DASH分片
我压制了5个不同清晰度的视频,分别是
- 2160p.mp4
- 1080p.mp4
- 720p.mp4
- 480p.mp4
- 360p.mp4
然后,打开cmd执行以下命令:
ffmpeg -i {input1}.mp4 -i {input2}.mp4 -i {input3}.mp4 -i {input4}.mp4 -i {input5}.mp4 -i audio.m4a -c copy -map 0 -map 1 -map 2 -map 3 -map 4 -map 5 -f dash -adaptation_sets "id=0,streams=v id=1,streams=a" {output}.mpd
上方命令中的:
{input1~5}
分别代表了你每一个清晰度的视频文件。
auido.m4a
是刚才生成的音频文件。
{output}
是你要输出的mpd文件,{output}
是文件名
-map 0~4
对应着上面5个清晰度的视频文件,如果有四个或更多(更少)清晰度的话可以自行加减 -map
的数量。
注意:上方命令千万不要换行!
可以新建一个文本文档把命令加进去,替换掉上面的一些内容(如:输入文件和输出文件),然后复制到命令行里面执行。
最终,你就会得到一个 .mpd
的文件和一堆m4s
文件。
4. 分析并修改 mpd 文件,减少载入时间
打开刚刚生成的mpd文件,可以看到文件开头如下。
<?xml version="1.0" encoding="utf-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
profiles="urn:mpeg:dash:profile:isoff-live:2011"
type="static"
mediaPresentationDuration="PT1M34.0S"
minBufferTime="PT10.0S">
我们来看标头结尾的地方:
minBufferTime="PT10.0S"
这个属性的意思是,视频必须至少缓冲 10 秒才能开始播放。这里的数字可能因压制参数不同而变化。
但是缓冲 10 秒太长了,不但没有必要,还会严重拖慢载入速度。实际上,一般载入一点就可以开始播放了。因此,我们可以把时间改为 1.0 秒。
minBufferTime="PT1.0S"
5. 在网页上播放 DASH 视频,实现自动切换清晰度
有很多 js 库可以播放 DASH 视频。本文使用谷歌 shaka 播放器播放 DASH 视频。
为什么不用 dash.js?
dash.js 似乎也是使用比较广泛的 DASH 播放库。但是在使用 dash.js
的过程中经常卡死,调试工具显示播放器反复请求同一分片。不确定是否是 GOP 未严格对齐的问题。
以下有2种方法提供参考,您可以自选一种进行设置。
5.1:DPlayer
请将以下代码输入到您的HTML中,进行测试。
关于DPlayer的更多信息,参见:dplayer.diygod.dev
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no">
<meta name="renderer" content="webkit">
<meta name="force-rendering" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>DPlayer</title>
</head>
<body>
<!-- DPlayer 播放器 -->
<div id="dplayer"></div>
<script>
const dp = new DPlayer({
container: document.getElementById('dplayer'),
video: {
url: '你的mpd文件地址',
type: 'shakaDash',
// shakaDash 配置
customType: {
shakaDash: (video, player) => {
const src = video.src;
const playerShaka = new shaka.Player(video);
playerShaka.load(src);
},
},
},
});
</script>
<!-- 引入shakaDash库 -->
<script src="https://cdn.jsdelivr.net/npm/shaka-player/dist/shaka-player.compiled.js"></script>
<!-- 引入DPlayer库 -->
<script src="https://cdn.jsdelivr.net/npm/dplayer@latest/dist/DPlayer.min.js"></script>
</body>
</html>
5.2:或者自己编写测试网页
先创建一个html文件:
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no">
<meta name="renderer" content="webkit">
<meta name="force-rendering" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>MPD Test</title>
</head>
<body>
<video id="video" src="将此文本替换为你的mpd文件地址" width="500" controls></video>
<script src="https://cdn.jsdelivr.net/npm/shaka-player/dist/shaka-player.compiled.js"></script>
<script>
function initApp() {
// 安装内置的腻子程序来修补浏览器的不兼容性
shaka.polyfill.installAll();
// 检查浏览器是否支持Shaka需要的基本api
if (shaka.Player.isBrowserSupported()) {
// 正常
initPlayer();
} else {
// 这个浏览器没有我们需要的api
console.error('浏览器不支持 shakaDash!');
}
}
function initPlayer() {
// 创建一个播放器实例
const video = document.getElementById('video');
const src = video.src;
const player = new shaka.Player(video);
player.configure({
streaming: {
bufferingGoal: 45,
bufferBehind: 5,
retryParameters: {
timeout: 0, // ms超时,超时后中止;0意味着永远
maxAttempts: 200, // 失败前的最大请求数
baseDelay: 100, // 重试之间的基本延迟(以毫秒为单位)
// backoffFactor: 2, // 重试之间的乘数后退因子
// fuzzFactor: 0.5, // 应用于每个重试延迟的模糊因素
}
},
abr: {
defaultBandwidthEstimate: 500, // 每秒位数,位/秒
switchInterval: 1
}
});
// 将播放器附加到窗口,以便在JS控制台中方便访问
window.player = player;
// 监听错误事件
player.addEventListener('error', onErrorEvent);
// 尝试加载一个清单,这是一个异步进程
player.load(src)
.then(() => {
// 如果异步加载成功,就会运行此操作。
console.log('视频正在载入');
})
.catch(onError); // 如果异步加载失败,则执行onError
}
function onErrorEvent(event) {
// 提取shaka.util,事件中的错误对象
onError(event.detail);
}
function onError(error) {
// 记录错误
console.error('Error code', error.code, 'object', error);
}
document.addEventListener('DOMContentLoaded', initApp);
</script>
</body>
</html>
这样就可以在网页中实现视频自适应网速的效果了。