草庐IT

VideoJS+HLS视频加密播放

寻找09之夏 2023-04-22 原文

前言

        前段时间遇到一个播放视频的项目,为了防止登录的用户下载项目的视频,所以需要对视频加密,即使用户下载也不能播放;因为前端采用videojs,最后确认方案是将mp4转m3u8文件格式,来实现视频文件加密播放。下面做一下总结。

一、什么是HLS

        HLS(HTTP Live Streaming的缩写)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。HLS协议基于HTTP协议,客户端按照顺序使用HTTP协议下载存储在服务器上的文件。HLS协议规定,视频的封装格式是TS(Transport Stream),除了TS视频文件本身,还定义了用来控制播放的M3U8文件(文本文件)。HLS协议的工作原理是把整个视频流分割成一个个小的TS格式视频文件来传输,在开始一个流媒体会话时,客户端会先下载一个包含TS文件URL地址的M3U8文件(相当于一个播放列表),给客户端用于下载TS文件。

二、M3U8格式标准介绍

        M3U8是一种常见的流媒体格式,主要以文件列表的形式存在,既支持直播又支持点播,尤其在Android、iOS等平台最为常用,下面就来看一下M3U8的最简单的例子:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.000000,
out0.ts
#EXTINF:10.000000,
out1.ts
#EXTINF:10.000000,
out2.ts
#EXTINF:10.000000,
out3.ts
#EXTINF:6.120000,
out4.ts

#EXTM3U:M3U8文件头,必须放在第一行。
#EXT-X-VERSION:M3U8文件的版本,常见的是3,其实版本已经发展了很多了。
#EXT-X-MEDIA-SEQUENCE :第一个TS分片的序列号,一般情况下是0,但是在直播场景下,这个序列号标识直播段的起始位置。
#EXT-X-TARGETDURATION:每个分片TS的最大的时长;例如:EXT-X-TARGETDURATION:10 ,表示每个分片的最大时长是10秒。
#EXT-X-ALLOW-CACHE:是否允许cache;例如:EXT-X-ALLOW-CACHE:YES 、EXT-X-ALLOW-CACHE:NO,默认情况下是YES。
#EXT-X-ENDLIST:M3U8文件结束符。
#EXTINF:extra info,分片TS的信息,如时长,带宽等;一般情况下是 #EXTINF:<duration>,[<title>] 后面可以跟其他的信息,逗号之前是当前分片的TS时长。分片时长要小于 EXT-X-TARGETDURATION 定义的值。
#EXT-X-DISCONTINUITY:该标签表明其前一个切片与下一个切片之间存在中断。
#EXT-X-PLAYLIST-TYPE :表明流媒体类型。
#EXT-X-KEY:是否加密解析。例如:#EXT-X-KEY:METHOD=AES-128,URI="https://example.com/video.key?token=xxx" 加密算法是AES-128,密钥通过请求 https://example.com/video.key?token=xxx 来获取,密钥请求回来以后存储在本地,并用于解密后续下载的TS视频文件。

上面介绍的是最常见的playlist,还有一种playlist,仅包含播放节目列表信息,在HLS中称为master playlist,也是二级索引的结构,其示例如下:

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1280000,AVERAGE-BANDWIDTH=1000000, RESOLUTION=720x480
http://example.com/low.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=2, BANDWIDTH=2560000,AVERAGE-BANDWIDTH=2000000, RESOLUTION=1080x720
http://example.com/mid.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=3, BANDWIDTH=7680000,AVERAGE-BANDWIDTH=6000000, RESOLUTION=1920x1080
http://example.com/high.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=4, BANDWIDTH=65000,CODECS="mp4a.40.5"
http://example.com/audio-only.m3u8

#EXT-X-STREAM-INF:用于标识一个Variant Stream,这是由一系列的Redition组成的。该标签的属性列表中包含了Variant Stream的描述信息。例如:BANDWIDTH表示Variant Stream中的峰值比特率,单位bits/s。
AVERAGE-BANDWIDTH表示Variant Stream中的平均比特率,单位bits/s。
CODECS包含Variant Stream中音视频编码格式相关的信息,比如上面的"mp4a.40.5"。
RESOLUTION包含Variant Stream中对应视频流的分辨率。
FRAME-RATE表示Variant Stream中的视频帧率。

三、FFmpeg 转HLS常见参数

        FFmpeg中自带HLS的封装参数,使用HLS格式即可进行HLS的封装,但是生成HLS的时候有各种参数可以进行参考,例如设置HLS列表中切片的前置路径、生成HLS的TS切片时设置TS的分片参数、生成HLS时设置M3U8列表中保存的TS个数等,详细参数如下表。

参数类型说明
start number整数设置M3U8列表中的第一片的序列数
hls time浮点数设置每一片时长
hls list size整数设置M3U8中分片的个数
hls ts options字符串设置TS 切片的参数
hls wrap整数设置切片索引回滚的边界值
hls allow cache整数设置M3U8中EXT-X-ALLOW-CACHE的标签
hls base url字符串设置M3U8中每一片的前置路径
hls segment filename字符串设置切片名模板
hls key info file字符串设置M3U8加密的key 文件路径
hls subtitle path字符串设置M3U8字幕路径
hls flags标签(整数)

设置M3U8文件列表的操作,具体如下。

singlefile:生成一个媒体文件索引与字节范围

delete_segments:删除M3U8文件中不包含的过期的TS切片文件

rounddurations:生成的M3U8切片信息的 duration 为整数

discont_start:生成M3U8的时候在列表前边加上 discontinuity 标签

omit endlist:在M3U8末尾不追加endlist标签

use localtime布尔设置M3U8文件序号为本地时间戳
use localtime mkdir布尔根据本地时间戳生成目录
hls playlist type字符串设置M3U8列表为事件或者点播列表
method字符串设置HTTP属性

四、视频切片加密

1.生成文件视频切片加密文件

基本命令:

#!/bin/sh
openssl rand 16 > file.key
echo file.key > file.keyinfo
echo file.key >> file.keyinfo
echo $(openssl rand -hex 16) >> file.keyinfo
 
备注:加密方式 ASE

参数详解:

openssl rand 16 > file.key 生成一个key文件

echo file.key > file.keyinfo 将外部访问的file.key映射到file.keyinfo文件中。

echo file.key >> file.keyinfo 将项目file.key所在的文件路径映射到fike.keyinfo文件中。

echo $(openssl rand -hex 16) >> file.keyinfo 生成IV密钥

Go实现:

# 生成 file.key
err = exec.Command("sh", "-c", "openssl rand 16 > file.key").Run()
if err != nil {
    // todo
}
# 生成 file.keyinfo
err = exec.Command("sh", "-c", "echo file.key > file.keyinfo" && echo echo file.key >> file.keyinfo && echo $(openssl rand -hex 16) >> file.keyinfo").Start()
if err != nil {
    // todo
}
 
备注:Run():启动指定的命令并等待其完成。 Start():启动指定的命令无需等待其完成。

2.FFmpeg 创建 HLS 播放清单(m3u8)

转化命令:

ffmpeg -y -i ocean.mp4 -c:v copy -hls_time 10 -hls_list_size 0 -hls_key_info_file file.keyinfo -hls_playlist_type vod -hls_segment_filename ocean%d.ts -f hls playlist.m3u8

参数详解:

-y  覆盖输出的文件

-i ocean.mp4 输入文件,源文件;

-c:v copy 表示不重新编码,在格式未改变的情况采用;

-hls_time 10 每片 TS 文件时长10秒;

-hls_list_size 0  不限制M3U8中分片的个数;

-hls_key_info_file file.keyinfo file.keyinfo  设置M3U8加密的 key 文件路径;

-hls_playlist_type vod  设置 M3U8 列表为点播;

-hls_segment_filename ocean%d.ts  设置切片名模板;

-f hls playlist.m3u8 指定输出格式hls,playlist.m3u8 输出文件名

Go实现:

cmd := exec.Command("ffmpeg",
    "-y",
    "-i", ocean.mp4,
    "-c:v", "copy",
    "-hls_time", "10",
    "-hls_list_size", "0",
    "-hls_key_info_file", file.keyinfo,
    "-hls_playlist_type", "vod",
    "-hls_segment_filename", "ocean%d.ts",
    "-f", "hls", "playlist.m3u8"))
 
err = cmd.Start()
if err != nil {
    // todo
}
 
err = cmd.Wait()
if err != nil {
    // todo
}
 
// todo
 
备注:cmd.Start():Start启动指定的命令,但不等待它完成。cmd.Wait():等待命令退出并等待任何复制到stdin或从stdout或stderr复制完成;这里用 Wait() ,是我后面有业务处理,需要确认这里成功执行。

执行结果:

3.FFmpeg 解密合成 TS

执行代码:

ffmpeg -allowed_extensions ALL -protocol_whitelist "file,http,crypto,tcp" -i playlist.m3u8 -c copy output.mp4

备注:如果解密无法访问 key.info,下载 key.info 文件,修改 playlist.m3u8 文件中"URI"位置,保证执行 ffmpeg 可访问到

五、VideoJS + M3U8 播放视频

本地搭建一个简单的Web服务,并解析一个虚拟域名"www.test.vip"(IP+端口也可以),将生成的 file.key 、playlist.m3u8 和视频切片 TS 文件放在 resource 目录下(只要能访问到即可)
前端代码和目录:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>PC HLS video</title>
    <link href="https://vjs.zencdn.net/7.20.3/video-js.css" rel="stylesheet"/>
</head>
<body style="text-align:center;">

<h1>PC 端播放 HLS(<code>.m3u8</code>) 视频</h1>
<p>借助 video.js 和 videojs-contrib-hls</p>
<p>由于 videojs-contrib-hls 需要通过 XHR 来获取解析 m3u8 文件, 因此会遭遇跨域问题, 请设置浏览器运行跨域</p>

<video id="video" class="video-js vjs-default-skin vjs-big-play-centered" controls style="margin: auto">
    <source src="resource/playlist.m3u8" type="application/x-mpegURL">
</video>
<script src="https://vjs.zencdn.net/7.20.3/video.min.js"></script>
<!-- PC 端浏览器不支持播放 hls 文件(m3u8), 需要 videojs-contrib-hls 来给我们解码 -->
<script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script>
<script>
    const player = videojs('video');
    player.play();
</script>
</body>
</html>

 

 运行结果:

有关VideoJS+HLS视频加密播放的更多相关文章

  1. 动漫制作技巧如何制作动漫视频 - 2

    动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、

  2. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  3. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  4. ruby - 使用 AES 的 Rails 加密,过于复杂 - 2

    我在加密来self正在使用的第三方供应商的值时遇到问题。他们的指令如下:1)Converttheencryptionpasswordtoabytearray.2)Convertthevaluetobeencryptedtoabytearray.3)Theentirelengthofthearrayisinsertedasthefirstfourbytesontothefrontofthefirstblockoftheresultantbytearraybeforeencryption.4)EncryptthevalueusingAESwith:1.256-bitkeysize,2.25

  5. ruby - 如何使用私钥加密完全加密 Ruby 中的数据? - 2

    首先,关于我们系统的一些信息,它基本上是建筑行业的电子招标解决方案。所以:列表项我们的系统有多家公司每个公司都有多个用户每家公司可以创建多个拍卖然后其他公司可以为可用的拍卖提交他们的出价。一个出价包含数百或数千个单独的项目,我们只需要加密这些记录的“价格”部分。我们面临的问题是,我们的大客户不希望我们知道投标价格,至少在投标过程中是这样,这是完全可以理解的。现在,我们只是通过对称加密对价格进行加密,因此即使价格在数据库中有效加密,他们担心的是我们拥有解密价格的key。因此,我们正在研究某种形式的公钥加密系统。以下是我们对解决方案的初步想法:当一家公司注册时,我们会使用OpenSSL为其

  6. ruby-on-rails - 我如何比较 'Bcrypt' Gem解密的密码和加密的密码 - 2

    我正在尝试对某些帖子的评论使用简单的身份验证。用户使用即时ID和密码输入评论我使用“bcrypt”gem将密码存储在数据库中。在comments_controller.rb中像这样@comment=Comment.new(comment_params)bcrypted_pwd=BCrypt::Password.create(@comment.user_pwd)@comment.user_pwd=bcrypted_pwd当用户想要删除他们的评论时,我使用data-confirm-modalgem来确认数据在这部分,我必须解密用户输入的密码以与数据库中的加密密码进行比较我怎样才能解密密码,

  7. ruby - 如何更改此正则表达式以从未指定 v 参数的 Youtube URL 获取 Youtube 视频 ID? - 2

    目前我正在使用这个正则表达式从YoutubeURL中提取视频ID:url.match(/v=([^&]*)/)[1]我怎样才能改变它,以便它也可以从这个没有v参数的YoutubeURL获取视频ID:http://www.youtube.com/user/SHAYTARDS#p/u/9/Xc81AajGUMU感谢阅读。编辑:我正在使用ruby​​1.8.7 最佳答案 对于Ruby1.8.7,这就可以了。url_1='http://www.youtube.com/watch?v=8WVTOUh53QY&feature=feedf'url

  8. ruby - 如何以编程方式将 mp3 转换为 itunes 可播放的 aac/m4a 文件? - 2

    我一直在寻找一种以编程方式或通过命令行将mp3转换为aac的方法,但没有成功。理想情况下,我有一段代码可以从我的Rails应用程序中调用,将mp3转换为aac。我安装了ffmpeg和libfaac,并能够使用以下命令创建aac文件:ffmpeg-itest.mp3-acodeclibfaac-ab163840dest.aac当我将输出文件的名称更改为dest.m4a时,它无法在iTunes中播放。谢谢! 最佳答案 FFmpeg提供AAC编码功能(如果您已编译它们)。如果您使用的是Windows,则可以从here获取完整的二进制文件。

  9. ruby - 如何在Elixir中使用AES CBC 128进行加密和解密 - 2

    我在Rails中有一个具有以下方法的应用程序,该方法可以加密和解密文本并与Java客户端通信。defencrypt(string,key)cipher=OpenSSL::Cipher::AES.new(128,:CBC)cipher.encryptcipher.padding=1cipher.key=hex_to_bin(Digest::SHA1.hexdigest(key)[0..32])cipher_text=cipher.update(string)cipher_textexcenddefhex_to_bin(str)[str].pack"H*"enddefbin_to_hex(

  10. ruby - 如何播放 mp3 文件? - 2

    我如何用ruby​​编写一个脚本,当从命令行执行时播放mp3文件(背景音乐)?我试过了run="mplayer#{"/Users/bhushan/resume/m.mp3"}-aosdl-vox11-framedrop-cache16384-cache-min20/100"system(run)但它也不起作用,以上是播放器特定的。如果用户没有安装mplayer怎么办。有没有更好的办法? 最佳答案 我一般都是这样pid=fork{exec'mpg123','-q',file} 关于ruby

随机推荐