首页 > 其他分享 >HLS视频加密,让您的视频内容更安全!

HLS视频加密,让您的视频内容更安全!

时间:2024-05-21 10:44:56浏览次数:17  
标签:视频 const src HLS hls 加密

** 背景介绍**

HLS视频加密是一种基于HTTP Live Streaming(HLS)协议的加密技术。它的核心思想是将视频切片进行加密处理,在客户端播放时需要先获取解密密钥才能正常偶发。通过这种方式,HLS加密可以有效防止未经授权的第三方窃取视频内容,从而保障了视频内容的版权和安全。数据万象媒体处理服务提供了一套HLS视频加密方案,方便用户各个场景的需求。

** HLS加密方案**

整体加密方案如下图所示:

** 痛点**

在我们日常的工作生活中,如果没有HLS加密,会带来以下问题:

视频内容被非法下载和分享:没有加密的视频内容容易被非法下载和分享,导致付费业务受到威胁。
影响用户体验:为了提高视频的安全性,可能需要采用更复杂的验证和授权机制。这可能会增加用户的操作复杂度,降低用户体验。
增加服务器的负担:如果采用客户端解密的技术,服务器需要处理更多的请求和计算量,可能会对延迟和性能造成一定的不良影响。

** 使用场景**

直播赛事:体育赛事、音乐会等大型活动需要进行直播,HLS加密可以有效防止盗版和非法传播。
在线教育:在线教育平台需要保护课程内容的版权,HLS加密可以确保课程内容不被非法窃取。
付费视频:电影、电视剧等付费视频内容需要进行版权保护,HLS加密可以有效防止盗版行为。
企业会议:企业的重要会议、内部培训等内容需要进行保密处理,HLS加密可以确保这些内容不被泄露。

** 操作指南**

生成加密视频

一、模版设置

  1. 开通媒体处理
    进入存储桶界面,点击数据处理中的媒体处理,点击开通。

  2. 创建HLS转码模版
    点击任务与工作流里的模版配置,点击创建转码模版
    2.1 输入模版名称,封装格式选择HLS。

2.2 打开视频加密开关
视频参数和音频参数根据需要填写,在高级设置里打开视频加密开关

二、创建转码任务

在当前存储桶上传任意视频文件,点击任务管理里的创建任务。

  1. 生成m3u8加密文件
    源文件路径选择刚刚上传的视频文件,模版类型选择自定义模版,选择第二步创建的hls转码模版,记住目标路径和目标文件名,产出文件就是我们需要的加密视频文件。

  2. 确定产物文件
    找到创建任务时填的产物路径,可看到生成后的加密文件

播放加密视频
控制台媒体处理,视频加密配置模块,展示播放密钥(playKey,部署后端服务的时候会用到)

拿到生成的m3u8视频文件和播放秘钥(playKey)后,就可以开始搭建服务,播放刚刚加密的m3u8视频文件。
本文前端部分以js代码为例,服务端以nodejs为例,来说明整个使用过程。

三、前端部分

  1. 首先下载hls加密代码包(https://bjtest-10008930.cos.ap-shanghai.myqcloud.com/hlsCode/hls加密代码包.zip)
  2. 在页面中引入压缩包中cos_hls.js、jsencrypt.js 和 hls.js。
  3. 根据播放器种类,在页面中引入压缩包中文件,目前支持三种类型(hls.js/tcplayer/video.js)。

hls.js:

<script src="./cos_hls.js"></script>
<script src="./hls.js"></script> 
<script src="./jsencrypt.js"></script>

tcplayer:

<link href="https://web.sdk.qcloud.com/player/tcplayer/release/v4.2.2/tcplayer.min.css" rel="stylesheet"/>
<script src="https://web.sdk.qcloud.com/player/tcplayer/release/v4.2.2/libs/hls.min.0.13.2m.js"></script>
<script src="https://web.sdk.qcloud.com/player/tcplayer/release/v4.2.2/tcplayer.v4.2.2.min.js"></script>
<script src="./cos_hls.js"></script>
<script src="./jsencrypt.js"></script>

video.js:

<link href="https://vjs.zencdn.net/8.11.8/video-js.css" rel="stylesheet" />
<script src="https://vjs.zencdn.net/8.11.8/video.js"></script>
<script src="./cos_hls.js"></script>
<script src="./jsencrypt.js"></script>
  1. 前端使用cos_hls.js文件中封装好的cosHls对象来播放m3u8文件,用户按照如下规则传入参数,即可实现播放功能。
<script>
    // cosHLs为cos_hls.js封装的对象,使用play方法播放视频文件
    cosHls.play({
        // video标签的id
        container: 'video',
        // 支持的播放器种类(hls.js/tcplayer/video.js)
        playerType: 'hls.js',
        // 请求m3u8接口的文件地址
        src: 'https://examplebucket-1250000000.cos.ap-beijing.myqcloud.com/hls/video.m3u8?ci-process=pm3u8',
        // 标记src里的域名是不是CDN域名(false/true)
        // useCdn: false,
        // 请求token和签名的函数
        getToken(opt, callback) {
            // 加密公钥,不需要用户填写,sdk会自动生成
            var publicKey = opt.publicKey;
            // 请求m3u8接口的文件地址,不需要用户填写,sdk会自动生成
            var src = opt.src;
            // 是否返回加密内容,与cosHls对象的ProtectContentKey参数保持一致,不需要用户填写,sdk会自动生成
            var protectContentKey = opt.ProtectContentKey;
            // 新建xhr对象,进行请求
            var xhr = new XMLHttpRequest();
            xhr.withCredentials = true;
            // /samples/hls/token为自定义请求地址,用户可自自定义
            xhr.open('POST', `/hls/token`, true);
            xhr.setRequestHeader('Content-Type', 'application/json')
            // 请求成功返回authorization 和 token
            xhr.onload = function () {
                var r = JSON.parse(xhr.responseText);
                var authorization = r.authorization
                var token = r.token
                callback(null, {authorization, token});
            };
            xhr.onerror = function () {
                callback('get token error');
            };
            // node服务所需要的参数,已从sdk获取,不需要用户填写
            var data = {
                src: src,
                publicKey: window.btoa(publicKey),
                protectContentKey: protectContentKey
            };
            xhr.send(JSON.stringify(data));
        }
    })
</script>

四、服务端部分
服务端,以 Nodejs 为例,主要代码如下:

const COS = require('cos-nodejs-sdk-v5');
const base64Url = require('base64-url');
const express = require('express');
const crypto = require('crypto');

// 配置参数
const config = {
    // 获取腾讯云密钥,建议使用限定权限的子用户的密钥 https://console.cloud.tencent.com/cam/capi
    secretId: process.env.SecretId,
    secretKey: process.env.SecretKey,
    // 播放秘钥,可在媒体处理模块获取 https://console.cloud.tencent.com/cos/bucket?bucket=xxxx-100000&region=ap-xxx&type=ci&anchorType=video
    playKey: process.env.playKey,
    // 目标存储桶名称,可在存储桶列表页获取 https://console.cloud.tencent.com/cos/bucket
    bucket: 'xxx',
    // 目标存储桶地域,可在存储桶列表页获取 https://console.cloud.tencent.com/cos/bucket
    region: 'xxx'
};

// 创建临时密钥服务和用于调试的静态服务
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

router.post('/hls/token', (req, res, next) => {
    // 从接口拿到文件地址,加密公钥,是否返回加密内容
    const body = req.body;
    const src = body.src;
    const publicKey = body.publicKey;
    const protectContentKey = body.protectContentKey;
    
    // 如在某些特殊场景需要用HLS标准加密(例如小程序里播放/iOSWebview),可以去掉下面的限制判断并做好来源限制只允许小程序来源。
    // 代码示例只允许 protectContentKey 传 1,原因:如果允许传入 0 播放流程会走 HLS 标准加密会有风险。
    const userAgent = req.headers['user-agent'] || '';
    const uaWhiteList = ['Safari', 'wechatdevtools', 'MiniProgramEnv'];
    const isUaAllow = uaWhiteList.some(item => userAgent.includes(item));
    // 只有白名单的浏览器,才能走标准加密
    if (!protectContentKey && !isUaAllow) {
        res.status(400);
        return res.send({code: -1, message: 'protectContentKey=0 not allowed'});
    }

    // src 链接校验
    if (!src || !srcReg.test(src)) return res.send({code: -1, message: 'src format error'});
    if (!publicKey) return res.send({code: -1, message: 'publicKey empty'});

    // 解析 url
    const { bucket, region } = config;
    const { token, authorization } = getToken({publicKey, protectContentKey, bucket, region, src}, res)
    res.send({code: 0, message: 'ok', token, authorization});
});

const srcReg = /^https?:\/\/([^/]+)\/([^?]+)/;
const ciHostReg = /^[^.]+\.ci\.[^.]+\.myqcloud\.com$/;

function getToken({publicKey, protectContentKey, bucket, region, src}) {
    const m = src.match(srcReg);
    const srcHost = m[1];
    const pathKey = m[2];
    const query = {};
    const isCiHost = ciHostReg.test(srcHost);
    src.replace(/^([^?]+)(\?([^#]+))?(#.*)?$/, '$3').split('&').forEach(item => {
        const index = item.indexOf('=');
        const key = index > -1 ? item.slice(0, index) : item;
        let val = index > -1 ? item.slice(index + 1) : '';
        query[key] = decodeURIComponent(val);
    });
    let objectKey = isCiHost ? query.object : pathKey;
    const header = {
        "alg": "HS256",
        "typ": "JWT"
    }
    const appId = bucket.slice(bucket.lastIndexOf('-') + 1);
    let payload = {
        Type: "CosCiToken",
        AppId: appId,
        BucketId: bucket,
        Issuer: "client",
        IssuedTimeStamp: Math.floor((new Date().getTime() - 30 * 1000) / 1000),
        ProtectSchema: "rsa1024",
        PublicKey: publicKey,
        ProtectContentKey: protectContentKey || 0,
        UsageLimit: 50,
        Object: objectKey,
    };
    let Header = base64Url.encode(JSON.stringify(header))
    let PayLoad = base64Url.encode(JSON.stringify(payload))
    let data = Header + "." + PayLoad
    let hash = crypto.createHmac('sha256', config.playKey).update(data).digest();
    let Signature = base64Url.encode(hash);
    let token = Header + '.' + PayLoad + '.' + Signature
    let authorization = COS.getAuthorization({
        SecretId: config.secretId,
        SecretKey: config.secretKey,
        Method: 'get',
        Pathname: `/${objectKey}`,
        Query: {'ci-process': 'pm3u8'},
    });
    return {token, authorization};
}

五、效果体验
完成前后端的代码后,启动服务,即可开始播放加密视频。

在线体验地址:
https://cos.cloud.tencent.com/samples/hls/private-encrypt/

方案接入优势

接入简单:支持多个开源通用播放器,定制化能力强。

支持场景丰富:PC Web、Android WebView,Android/iOS移动端App

不兼容的场景自动降级:因为 iOS Webview 不兼容 Media Source Extensions,会自动降级为标准加密方案。减少开发兼容成本。

总结

数据万象媒体处理新增视频加密,旨在让用户能够更加方便地使用视频加密功能,提高用户体验。同时,我们也会继续关注用户的反馈,不断优化和改进数据万象媒体处理的用户体验,为用户提供更好的服务。

标签:视频,const,src,HLS,hls,加密
From: https://www.cnblogs.com/cloudstorageangel/p/18203448

相关文章

  • video2blog 视频转图文AI小工具正式开源啦
    前言最近对一些小细节做了很多处理,但是其实还是有非常多的问题,没办法时间毕竟时间有限。为什么在这个时候开源,因为主要功能可以全部跑通了,分支暂时没开发的功能也可以通过其他的工具来替代。这个工具开发初衷(想法来源),我之前有一篇文章有详细的说明,有兴趣的可以看一下https://mp.......
  • 3DES加密、解密工具类,有需要的直接cv大法拿去用吧
    package你的类路径;importcn.hutool.core.codec.Base64;importjavax.crypto.BadPaddingException;importjavax.crypto.Cipher;importjavax.crypto.IllegalBlockSizeException;importjavax.crypto.NoSuchPaddingException;importjavax.crypto.spec.SecretKeySpec;importjav......
  • python 国密sm2(C1C3C2) sm4(CBC) 加密 解密
    fromgmssl.sm4importCryptSM4,SM4_ENCRYPT,SM4_DECRYPTimportbinasciiimportbase64fromgmsslimportsm2,func#GMSSLforPython#安装pipinstallgmssl#keycode='101231221289195374403401962572899'key='1012312212891953'iv=......
  • 某东h5st4.7 加密参数(二)
    接着上一篇文章,由于最近比较忙,没有时间看。今天有时间看看上一篇没有说完的其他加密参数。仅供学习交流!1、fp的生成,搜索关键词fingerprint,即可查看到生成位置调试可以找到生成位置2、请求获取tkalgo中参数expandParams,如下图调试可以获取到参数expandParams从此可......
  • 本打算写个抖音视频下载器
    之前抖音的视频的下载地址是写在页面里的,不知道什么时候改成异步请求了,写到最后发现烂尾了,如果用c++来执行js获取token那就太费劲了,这事还是交给python干合适。但是代码写都写了也别浪费,留在这里以后没准能用上#include<iostream>#include<fstream>#include<string>#incl......
  • 正式开启全站HTTPS加密之旅
    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解`正式开启全站HTTPS加密之旅日期:2017-7-14阿珏谈天说地浏览:2158次评论:0条经过有段时间的内测,博客正式开启全站https。建站到......
  • 国产Linux音视频聊天程序开发遇到的坑及解决:相互听不到对方声音?
       最近完成了一个银河麒麟上的视频聊天项目,在我们开发机上测试一切正常后,提交给甲方测试。结果发现在甲方的某些银河麒麟V10的电脑上,听不到声音。   这个问题,使用《Avalonia实现跨平台的IM即时通讯、语音视频通话(源码,支持信创国产OS,统信、银河麒麟)》这个Demo就可以......
  • 如何自动(定时/间隔/重复)执行 同步文件、备份打包加密压缩文件
    首先,需要用到的这个工具:度娘网盘提取码:qwu2蓝奏云提取码:2r1z 参考下列两个之前发布的教程结合使用即可:《快捷自由定时重启、注销、关机》《如何从多个文件夹内转移全部文件(忽略文件夹的结构)(进行复制)(再打包)》就是先设定好勾选对'来源路径’Zip打包,并且勾选备份模式备份......
  • 【一步步开发AI运动小程序】十七、如何识别用户上传视频中的运动、动作、姿态?
    【云智AI运动识别小程序插件】,可以为您的小程序,赋于人体检测识别、运动检测识别、姿态识别检测AI能力。本地原生识别引擎,内置10余个运动,无需依赖任何后台或第三方服务,有着识别速度快、体验佳、扩展性强、集成快、成本低的特点,本篇实现需要使用此插件,请先行在微信服务市场或官网了......
  • Vue3使用SM国产加密库
    npm安装npminstall--savesm-crypto//使用import{sm2,sm3,sm4}from'sm-crypto'//-----------sm2--------------------//获取密钥对letkeypair=sm2.generateKeyPairHex()publicKey=keypair.publicKey//公钥privateKey=keypair.privateKey//私钥//......