热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于HLS流媒体协议视频加密的解决方案

背景付费观看视频的模式是很多平台的核心业务,如果视频被录制并非法传播,付费业务将受到严重威胁。因此对视频服务进行加密的技术变得尤为重要。本文所指的视频加密是为了让要保护的视频不能轻

背景

付费观看视频的模式是很多平台的核心业务,如果视频被录制并非法传播,付费业务将受到严重威胁。因此对视频服务进行加密的技术变得尤为重要。

本文所指的视频加密是为了让要保护的视频不能轻易被下载,即使下载到了也是加密后的内容,其它人解开加密后的内容需要付出非常大的代价。

无法做到严格的让要保护的视频不被录制,原因在于你需要在客户端播放出视频的原内容,解密的流程在客户端的话不法分子就能模拟整个流程,最保守也能用屏幕录制软件录制到视频的原内容(可以通过加水印的方法缓解下)。我们的目标是让他获取原内容的代价更大。

本文为大家提供了一套简单的基于HLS流媒体协议,使用video.js + NodeJS + FFmpeg等相关技术实现的m3u8+ts+aes128视频加密及播放的解决方案示例。

目录

  • 项目简介
  • 项目启动
  • 项目原理
  • 技术栈
  • 源码简析
  • 建议

项目简介

  起初是为了将工作中已有的基于Flash的视频播放器替换为不依赖Flash的HTML5视频播放器,主要使用了现有的video.js开源播放器做的定制化开发。当完成视频播放器的制作后,在进一步延伸Web端视频加密的相关内容时,开始了解并逐渐深入的研究了相关视频加密内容。最终通过整理归纳,以及自身的理解,做了这个简单的Demo。目的是为了能够给在视频加密这方面有相同目的的道友提供微薄的帮助,要是能起到抛砖引玉的效果,自然是再好不过了。

项目启动

1.安装项目环境


  • 安装node、npm环境
  • 根据app目录下的package.json安装对应的npm包
  • 安装ffmpeg

2.启动项目


  • 在app目录下,输入npm start,启动项目
  • 在浏览器中访问 http://localhost:3000
  • 按照页面中的顺序进行相关操作

3.权限登录


  • 用户名:admin
  • 密码:admin

项目原理

  本项目的核心原理其实就是讲解了一个视频源从正常的mp4格式如何变为加密后的m3u8文件+ts文件+key秘钥文件,之后又如何在服务端被限制访问,最终能够在客户端正常播放的视频加密、解密并播放的流程。

项目原理图示


 

项目原理图

 

 

技术栈

  • NodeJS + Express 实现服务器开发
  • FFmpeg + fluent-ffmpeg 实现node环境下的视频转码、加密
  • socket.io 通过websocket相关的类库,实现实时输出FFmpeg进行的视频转码、加密操作
  • video.js + videojs-contrib-hls.js 实现客户端的视频解密及播放
  • html + css + js 实现简单的前端开发

源码简析

项目目录说明



video-hls-encrypt/ .............................. hls视频加密项目根目录
├── app/ .............................. express框架默认的app根目录
│ ├── bin/ .............................. express框架启动的bin目录
│ │ └── www .............................. express框架启动的www文件
│ ├── controllers/ .............................. 项目控制器目录,服务器相关的逻辑代码
│ │ ├── encrypt.js .............................. 加密逻辑代码
│ │ └── upload.js .............................. 上传逻辑代码
│ ├── node_modules/ .............................. express框架需要的相关npm依赖包,即package.json文件相对应的依赖包
│ │ └── ...
│ ├── public/ .............................. express框架静态文件目录,客户端请求的相关静态文件
│ │ ├── Javascripts .............................. 客户端的js文件目录
│ │ │ ├── encrypt.js .............................. 加密功能相关逻辑代码
│ │ │ ├── index.js .............................. 主页相关逻辑代码
│ │ │ ├── player.js .............................. 播放器相关逻辑代码
│ │ │ ├── socket.io.js .............................. socket.io.js 类库源文件
│ │ │ └── utils.js .............................. 工具类
│ │ ├── key/ .............................. 秘钥相关目录
│ │ │ ├── encrypt.key .............................. 秘钥文件
│ │ │ └── key_info.key .............................. ffmpeg加密视频转换相关文件
│ │ ├── libs/ .............................. 第三方类库目录
│ │ │ ├── videojs/ .............................. videojs 相关代码
│ │ │ └── videojs-contrib-hls/ .............................. videojs-contrib-hls 相关代码
│ │ ├── stylesheets/ .............................. css样式目录
│ │ │ └── common.css .............................. 通用样式表
│ │ └── videos/ .............................. 视频资源目录
│ │ ├── encrypt/ .............................. 加密后的视频资源目录
│ │ └── noencrypt/ .............................. 加密前的视频资源目录
│ ├── routes/ .............................. express框架路由目录
│ │ └── router.js .............................. express路由
│ ├── views/ .............................. express框架ejs模板目录
│ │ ├── encrypt.ejs .............................. 视频加密页面
│ │ ├── error.ejs .............................. 错误页面
│ │ ├── index.ejs .............................. 主页
│ │ ├── login.ejs .............................. 登录页面
│ │ ├── player.ejs .............................. 播放器页面
│ │ └── upload.ejs .............................. 上传视频页面
│ ├── app.js .............................. express程序入口
│ ├── nodemon.json .............................. node服务器热更新插件nodemon对应的配置文件
│ └── package.json .............................. express框架需要的第三方依赖包配置文件
├── .gitignore
├── README.md .............................. 项目说明文档
└── TODO-List.md .............................. 项目开发计划文档

源码简析


  • 简单的权限判断,app.js中:
    • express的中间件
    • 判断请求的后缀
    • 判断session中是否有用户名,有则允许访问 .key文件;没有则禁止访问
    • 主要是保护.key文件,可以加入其它的权限手段,比如token、session有效时长等等


//静态资源访问限制
app.use(function (req, res, next) {var suffix = /(\.key)$/g;//后缀格式指定if ( suffix.test(req.path)) {console.log(req.session.username,'++++请求key文件了');if((req.session.username != 'admin')){return res.send('请求非法');}else{console.log('+++++请求key文件了,并且已经登录,登录名为:',req.session.username);next();}}else {next();}
});

  • 利用FFmpeg对视频进行加密、切片处理,在encrypt.js中:
    • 利用了FFmpeg的切片和加密方法
    • 建议可以深入研究FFmpeg框架的相关api
    • 可以根据实际业务来对视频进行更符合要求的切片处理


/*** 加密处理方法* @param options 加密数据的相关参数* @param socket socket输出* @param callback 回调函数*/
function encryptFun(options,socket, callback) {var _name = options.fileName.split('.')[0];var _type = options.fileName.split('.')[1];var _encryptPath = options.encryptPath + '/' + _name;var _videoPath = options.noencryptPath + '/' + options.fileName;var _keyInfoPath = './public/key/key_info.key';var _outputPath = _encryptPath + '/playlist.m3u8';console.log('begin encrypt Fun');if (_type == 'mp4') {ffmpegCommand(_videoPath).addOption('-hls_time', '10') //设置每个片段的长度.addOption('-hls_key_info_file', _keyInfoPath).save(_outputPath).on('end', function () {socket.emit('encrypt-event',{msg:'Encrypt the ' + options.fileName + ' file OK!',type:1});callback(null, 'Encrypt the ' + options.fileName + ' file OK!');}).on('stderr', function (stderrLine) {console.log('Stderr output: ' + stderrLine);socket.emit('encrypt-event',{msg:stderrLine});}).on('error', function (err, stdout, stderr) {console.log('Cannot process video: ' + err.message);socket.emit('encrypt-event',{msg:err.message});callback(err, err.message);});}else{callback('type err','file type is not mp4.');}
}

  • 视频播放相关逻辑,player.ejs中:
    • 使用了videojs作为播放器插件
    • 使用了videojs-contrib-hls作为切片流解码插件
    • 具体的逻辑代码在player.js中






建议

  • 本项目更多的价值在于展示出一整套的加密原理,同时为了证明这套原理的可行性,做的比较简单的示例。
  • 本项目不会提供相关技术栈的使用教程。
  • 如果需要在实际应用中使用相关原理或技术栈,建议根据实际项目对部分或整体解决方案进行完善和扩展。

杂谈

以下的内容均为个人观点,仅供参考

  由于本人自身是做前端开发的,所以很多相关的示例都是基于前端考虑,对于后端的相应的策略并不是很专业。比如后端服务器,也采用的是偏前端的NodeJS。我想表达的是,在整套解决方案中,我主要做了3件事:

  • 第一,把mp4的视频源通过FFmpeg转换为加密后的m3u8文件和ts文件以及关键的加密密钥key文件;
  • 第二,通过最简单的权限访问,保护加密密钥key文件;
  • 第三,利用video.js及相关的videojs-contrib-hls.js实现客户端的视频文件解密,并播放。

  因此可以看出关于视频加密的解决方案中,最重要的其实是如何保护加密密钥key文件,而这部分工作更多的是在于服务器端的相关策略,比如可以使用COOKIEsession相关技术、添加自定义token校验、有效时长机制等等方法保证秘钥key文件的相对安全性、可靠性。  

  而如何将视频源文件转化为对应的加密后的文件,可以更多的研究开源库FFmpeg的使用,甚至如果没有迫切需求,可以考虑使用第三方视频云服务商的相关解决方案。至于客户端的视频解密,也可以研究video.js相关的内容。

完整项目

github.com/hauk0101/vi…

参考资料

  • 流媒体加密 : github.com/gwuhaolin/b…
  • Video.js: The Player Framework: videojs.com
  • FFmpeg: www.ffmpeg.org

浏览知识共享许可协议



作者:hauk0101

链接:https://juejin.im/post/6844903846389481480

来源:掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


推荐阅读
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 在Android中解析Gson解析json数据是很方便快捷的,可以直接将json数据解析成java对象或者集合。使用Gson解析json成对象时,默认将json里对应字段的值解析到java对象里对应字段的属性里面。然而,当我们自己定义的java对象里的属性名与json里的字段名不一样时,我们可以使用@SerializedName注解来将对象里的属性跟json里字段对应值匹配起来。本文介绍了使用@SerializedName注解解析json数据的方法,并给出了具体的使用示例。 ... [详细]
  • uniapp开发H5解决跨域问题的两种代理方法
    本文介绍了uniapp开发H5解决跨域问题的两种代理方法,分别是在manifest.json文件和vue.config.js文件中设置代理。通过设置代理根域名和配置路径别名,可以实现H5页面的跨域访问。同时还介绍了如何开启内网穿透,让外网的人可以访问到本地调试的H5页面。 ... [详细]
author-avatar
brucegogo03
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有