视频流媒体播放

229 阅读4分钟

为什么要用流媒体

在一个春光明媚的上午。你正哼着小曲,逛着掘金,突然PM跑过来跟你说,我们网站要酷炫,要有很多动效果,最亮眼的地方就是一个视频 banner。很常见的一个场景对吧,然后就甩给你了一个附件,50mb.mp4,你一脸愁容的跟PM解释这个太大了会大大影响用户体验,能不能小一点,得到的回答 "这个是业务老大指名要的,我也没有办法"。怎么办呢,那只能靠技术来解决问题啦。

什么是HLS(HTTP Live Streaming)

  • 它最初是苹果公司针对iPhone、iPod、iTouch和iPad等移动设备而开发的流,现在在很多桌面也有很多应用,HTML5就直接支持这个。
  • HLS 是苹果公司提出的基于HTTP的流媒体网络传输协议。类似于MPEG-DASH,但是HLS更加简洁。

原理

把文件或者媒体流按照不同的码率切分成一个个小片段进行传输,客户端在播放码流时,可以根据自身的带宽及性能限制,在同一视频内容的不同码率的备用源,选择合适码率的码流进行下载播放。

在传输会话开始时,客户端首先需要下载描述不同码流元数据的M3U8索引文件(类似于DASH中的MPD文件)。

与基于UDP的RTP协议不同,HLS请求仅使用HTTP传输,因此可以穿过任何允许HTTP数据通过的防火墙或代理服务器。

缺点

HLS协议的小切片(.ts)方式会生成大量的文件,存储或处理这些文件会造成大量资源浪费。因此,HLS协议对存储I/O要求相当苛刻。(可以用内存代替磁盘进行优化)

因为至少要有一段TS文件生成和完全下载才能正常播放。采用HLS直播的视频流延时一般在10秒以上,使用推荐配置时延迟大概在30S,而RTMP直播的延迟最低可达到3/4秒,因此,在对实时性要求较高的场合,如互动直播,就要慎用HLS。

ffmpeg安装

ffmpeg就是我们要用的视频编辑器(流媒体制作工具)

进入官网,选择需要下载的文件,官方网址:
ffmpeg.org/download.ht…
windows系统下需要下载二进制文件,我选择通过红色框选出进入新的页面下载。

image.png

image.png 下载完成以后,用winRAR或者任意解压工具解压,然后进入bin文件夹

image.png

复制这个路径

image.png

然后在电脑搜索里搜"编辑系统环境变量",选择环境变量-系统变量-Path-编辑,添加进去,确定即可。该设置是win10设置,其他的系统可能需要通过";"分割。

image.png

image.png

image.png

检验是否添加成功

win+R 然后输入ffmpeg,就会显示一下内容

image.png

如果显示找不到,可以尝试以下方法:

  1. 将命令行全关掉,重启开启。
  2. echo %PATH% 查看
  3. 如果重启命令行也出不来,打印的path也有配置上没有问题,那么可以尝试重启电脑

ffmpeg使用

查看视频文件的元信息,比如编码格式和比特率,可以只使用-i参数。

ffmpeg -i input.mp4

上面命令会输出很多冗余信息,加上-hide_banner参数,可以只显示元信息。

ffmpeg -i input.mp4 -hide_banner

ffmpeg如何控制码率。 ffmpg控制码率有3种选择,-minrate -b:v -maxrate ffmpeg官方比较建议,设置b:v时,同时加上 -bufsize -bufsize 用于设置码率控制缓冲器的大小,设置的好处是,让整体的码率更趋近于希望的值,减少波动。(简单来说,比如1 2的平均值是1.5, 1.49 1.51 也是1.5, 当然是第二种比较好) -minrate -maxrate 在线视频有时候,希望码率波动,不要超过一个阈值,可以设置maxrate。

ffmpeg -i input.mp4 -b:v 2000k -bufsize 2000k -maxrate 2500k output.mp4

视频切割, hls_time为时间,比如我选择10s切一个视频,总共45s就是5个

ffmpeg -v verbose -i output.mp4  -vf scale=1920:1080 -c:a aac -c:v libx264  -hls_time 10 -hls_playlist_type vod -b:v 2000k -maxrate 2500k -bufsize 2000k -b:a 96k -hls_segment_filename 1920p_%03d.ts -f hls 1920p.m3u8

然后引用hls工具,就可以直接在页面上播放你的视频流啦

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>hls-demo</title>
    <style>
        #video {
            display: block;
            margin: 0 auto;
        }
    </style>
</head>
<body>
<div>播放视频测试</div>
<video id="video" controls></video>
</body>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
    var video = document.getElementById('video');
    var m3u8 = "./video/1920p.m3u8";
    if (Hls.isSupported()) {
        var hls = new Hls();
        hls.loadSource(m3u8);
        hls.attachMedia(video);
        hls.on(Hls.Events.MANIFEST_PARSED, function() {
            video.play();
        });
    } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
        video.src = m3u8;
        video.addEventListener('loadedmetadata', function() {
            video.play();
        });
    }
</script>
</html>

network也可以看到你的视频流获取啦

image.png

参考参数

参数说明
-v verbose与log有关
-i mv.mp4指定输入文件名
scale 简写 -s分辨率
-c:a指定音频编码器
-c:v指定视频编码器
-b:v主要控制视频平均码率 (ffmpg控制码率有3种选择,-minrate -b:v -maxrate)
-b:a音频码率
-bufsize码率控制缓冲器的大小
-hls_time切割时间

react里使用

react里面使用也很简单,只要安装hls.js,然后

import Hls from 'hls.js';
import { useEffect, useRef } from 'react';

const Video = () => {
  const video = useRef<HTMLVideoElement>(null);

  useEffect(() => {
    if (!video.current) return;
    const m3u8 = '/public/1920p.m3u8';
    if (Hls.isSupported()) {
      const hls = new Hls();
      hls.loadSource(m3u8);
      hls.attachMedia(video.current);
      hls.on(Hls.Events.MANIFEST_PARSED, handleVideoPlay);
    } else if (video.current.canPlayType('application/vnd.apple.mpegurl')) {
      video.current.src = m3u8;
      video.current.addEventListener('loadedmetadata', handleVideoPlay);
    }
  }, []);

  const handleVideoPlay = async () => {
    video.current.play();
  };
  return (
    <section
    >
      <video src="" ref={video}></video>
    </section>
  );
};

export default Video;

参考文献

「1.4万字」玩转前端 Video 播放器

ffmpeg安装

web视频——视频点播——视频数据分段加载