使用MPEG DASH (Shaka)让视频画质自动适应网速

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文件。
m4s
mpd

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.js.org

<!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>
    <style type="text/css">
        a:link {
            text-decoration: none;
        }

        a:visited {
            text-decoration: none;
            color: #FFF;
        }

        a:hover {
            text-decoration: none;
        }

        a:active {
            text-decoration: none;
        }
    </style>
</head>

<body>
    <!--DPlayer播放器-->
    <div id="dplayer"></div>
    <!--引入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>
    <script>
        const dp = new DPlayer({
            container: document.getElementById('dplayer'),
            video: {
                url: '将此文本替换为你的mpd文件地址',
                type: 'shakaDash',
                //shakaDash配置
                customType: {
                    shakaDash: function (video, player) {
                        var src = video.src;
                        var playerShaka = new shaka.Player(video);
                        playerShaka.load(src);
                    },
                },
            },
        });
    </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() {
            // 创建一个播放器实例。
            var video = document.getElementById('video');
            var src = video.src;
            var 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(function () {
                //如果异步加载成功,就会运行此操作。
                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>

这样就可以在网页中实现视频自适应网速的效果了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值