学了半天终于懂了一点点,先记下步骤来,防止将来忘了/(ㄒoㄒ)/~~同时也分享给大家~

用到了这些:unity,AVProVideo插件,ffmpeg命令(需要安装ffmpeg),Git Bash命令(需要安装Git)

ffmpeg和git安装教程很多,这里就不说了。另外,据我了解AVPro的版本需要Ultra版本,才有解密功能好像,不太确定,我用的是下面这个,是可以的。

不分享资源了先,没找到资源怎么上传,总是说资源已存在,以后有空再研究吧

大体思路:首先设置一个密钥,然后用这个密钥将.mp4文件切成.m3u8文件以及多个加密的ts分片,因为AVProvideo可以播放.m3u8,高版本的AVPro也自带了拿key解密的功能,而且还能用请求头带着token去拿key(这个我目前还没有尝试)

因为将key写到本地会有被泄漏的风险,所以尽量不把key放本地。

我目前测试是在本地服务器测的,把key以及视频的加密分片都放本地服务器了,第一次播放视频从服务器下载分片后,再去服务器获取key,然后解密播放。

1.随机生成16byte的key文件,用于存放密钥。

在要存放.key文件的文件夹里,打开Git bash,里面输入(一个空格都不能错):

openssl rand 16 > enc.key

然后这个路径里会新增一个文件,名字叫enc.key

不放心的话可以验证key的长度,是不是16字节

ls -l enc.key

2.创建enc.keyinfo文件

在和enc.key同一目录下,新建文件:enc.keyinfo,内容如下:

http://192.168.31.13:80/videos/enc.key
enc.key
00000000000000000000000000000001

第一行:key文件在服务器的地址,播放器获取 Key 解密的 URL

第二行:key文件的路径,ffmpeg拿着它去加密

第三行:我也还不是很清楚,照抄完事

3.用这个key加密视频切片

ffmpeg命令,也可以在这个Git Bash里面执行,可以自己修改里面的参数,比如切片时长,名称之类的

ffmpeg -i input.mp4 -hls_time 4 -hls_playlist_type vod -hls_key_info_file enc.keyinfo -hls_segment_filename "out_%03d.ts" out.m3u8

等执行完后,文件夹里会生成.m3u8文件以及视频的切片,因为已经加密,所以双击切片不能正常播放。

另外,再分享一个不加密的切片命令:

ffmpeg -i input.mp4 -hls_time 4 -hls_playlist_type vod -hls_segment_filename "test_%03d.ts" test.m3u8

这种的因为没有加密,所以切出来的片可以正常播放。

可以看一眼.m3u8文件里,加密后的.m3u8文件里的内容会比不加密的.m3u8文件内容多一行URI,也就是获取key的路径。

4.测试播放

如果视频在本地,在gitBash里用ffplay -protocol_whitelist "file,http,https,tcp,tls,crypto,data" out.m3u8可以直接播放。

如果把视频放到服务器上了,可以直接在edge浏览器输入.m3u8文件的url访问了,如下图。

5.在unity中用AVPro解密并播放
using System;
using System.Collections;
using System.Collections.Generic;
using RenderHeads.Media.AVProVideo;
using UnityEngine;
using UnityEngine.Networking;

public class AvproPlayer : MonoBehaviour
{
    public MediaPlayer mediaPlayer;
    string m3u8Url = "http://192.168.31.13/videos/out.m3u8";
    void Start()
    {
         Play(m3u8Url);
    }
    public void Play(string m3u8Url)
    {
        mediaPlayer.PlatformOptionsWindows.videoApi = Windows.VideoApi.WinRT;
        StartCoroutine(GetKey(m3u8Url));
    }
    IEnumerator GetKey(string m3u8Url)
    {
        UnityWebRequest request = UnityWebRequest.Get("http://192.168.31.13/videos/enc.key");
        yield return request.SendWebRequest();
        if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError || request.result == UnityWebRequest.Result.DataProcessingError)
        {
            Debug.Log("获取失败" + request.error);
            yield break;
        }
        if (request.result == UnityWebRequest.Result.Success)
        {
            byte[] data = request.downloadHandler.data;
            Debug.Log("获取key成功" + request.downloadHandler.text);
            mediaPlayer.CloseMedia();
            mediaPlayer.PlatformOptionsWindows.keyAuth.overrideDecryptionKey = data;
            Debug.Log("设置key成功" + data.Length);
            mediaPlayer.OpenMedia(MediaPathType.AbsolutePathOrURL, m3u8Url, false);
            while(!mediaPlayer.Control.CanPlay())
            {
                yield return null;
            }
            mediaPlayer.Play();
        }
    }
}

里面的.m3u8和key地址换成自己的就行。

此时代码里已经有了从服务器获取key值,.m3u8里面的URI的值就无所谓了,甚至写一个不存在的路径也可以,因为overrideDecryptionKey优先级比文件里的级别高,毕竟它都叫override了...

但是直接赋值给overrideDecryptionKey好像说适合用来调试,真正项目里还是推荐用Auth Token去获取密钥,或者直接在m3u8里写明URI获取

Logo

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。

更多推荐