在线教育机构的视频如何做防下载和防盗录?

news2024/12/28 6:07:17

在线教育平台付费课程、企业内训的培训课程,这类视频课程内容是如何做防下载和防盗录的?

1.AI隐形溯源水印

这个功能能够将水印隐藏在视频中,不会影响观看体验,但却能够帮助企业很好的视频版权保护。更重要的是,对于盗录侵权内容,我们可以通过这个功能做溯源,追踪侵权行为。

 图:AI隐形溯源水印

2.VRM分片错序视频加密

采用分布式编码技术,将视频文件物理切片,每片视频进行多种算法混合型加密, 同时结合独立研制密码本,将关键数据进行错序混淆,对视频文件进行最高级别加密,这样经过加密的视频内容即使被下载,也无法进行恶意的二次分发,视频破解难度倍增。

3.Html5全链路视频加密

市面上常见的H5加密,采用标准的Apple HLS Encryption 视频保护机制,我们在此基础上进行深度优化,对密钥key进行深度加密,同时实现对视频播放器与视频数据文件双重加密处理,形成端到端的全链路视频安全防护,即使视频文件被盗用,其他应用也无法播放,让视频更加安全。

 我们的加密调用方法示例:

<div id="player"></div>
<script src="//player.polyv.net/script/player.js"></script>
<script>
var player = polyvPlayer({
    wrap: '#player',
    width: 800,
    height: 533,
    vid: '88083abbf5bcf1356e05d39666be527a_8',   
    playsafe:'81814fed-bdd0-4506-bec1-ebc8093148c5-hfevwsfxcsbcocx', 
  //playsafeUrl:'https://myDomain.com/token', // 业务方自定义的获取播放凭证接口URL,与playsafe参数二选一
    ts:'1568131545000',
    sign:'88313661ba7ded642c7b557b0a364b4b'
});

//切换加密视频时,需要重新获取播放凭证。如果初始化播放器时使用了playsafeUrl参数,则播放器会自动获取新的凭证,无需传playsafe参数。
player.changeVid({
  vid: '88083abbf5bcf1356e05d39666be527a_9', //需要切换的视频vid
  playsafe: '81814fed-bdd0-4506-bec1-ebc8093148c6-hfevwsfxcsbcocx', //新获取的playsafe token
  sign: '88313661ba7ded642c7b557b0a364b4c', //新获取的sign和ts参数
  ts: '1568131545001'
});
</script>

Web页面播放加密视频前,需要先访问业务方自己的服务端授权验证接口(可以在这里加上自有业务的授权验证逻辑,例如是否登录、是否购买课程等, 建议使用HTTPS)。如果业务上允许播放,则通​ 过创建 Playsafe Token接 ​口获取播放凭证(或者在服务端生成sign、ts参数),并返回给Web端播放器。

服务端生成播放凭证代码示例:

// 接口中应附带自有业务的授权验证逻辑,如判断是否登录、是否购买课程等

// 以下为生成播放凭证的代码示例
function get_client_ip() {
  if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
  } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
      $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
  } else {
      $ipaddress = $_SERVER['REMOTE_ADDR'];
  }
    return $ipaddress;
}

$userId = 'your userId';       // 保利威点播账号的userId
$secretkey = 'your secretkey';     // 保利威点播账号的secretkey
$videoId = '88083abbf5bcf1356e05d39666be527a_8';  // 视频vid
$ts = time() * 1000;      // 时间戳
$viewerIp = get_client_ip();  // 观众ip
$viewerId = '12345';      // 观众id
$viewerName = 'testUser';  // 观众昵称, 若值为中文需要urlencode('张三')
$extraParams = 'HTML5';  // 自定义扩展参数
$disposable = false // true 表示 token 仅一次有效。false 则表示在有效期内可以多次验证。默认为 false。

/* 将参数 $userId、$secretkey、$videoId、$ts、$viewerIp、$viewerIp、$viewerId、$viewerName、$extraParams按照ASCKII升序 key + value + key + value ... +value 拼接
*/
$concated =  'extraParams'.$extraParams.'ts'.$ts.'userId'.$userId.'videoId'.$videoId.'viewerId'.$viewerId.'viewerIp'.$viewerIp.'viewerName'.$viewerName;
// 首尾加上secretkey值
$plain = $secretkey.$concated.$secretkey;
// 取大写MD5
$sign = strtoupper(md5($plain));

// 然后将下列参数用post请求  https://hls.videocc.net/service/v1/token 获取 token
$url = 'https://hls.videocc.net/service/v1/token';
$data = array('userId' => $userId, 'videoId' => $videoId, 'ts' => $ts, 'viewerIp' => $viewerIp, 'viewerName' => $viewerName, 'extraParams' => $extraParams, 'viewerId' => $viewerId, 'sign' => $sign);
$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded",
        'method'  => 'POST',
        'content' => http_build_query($data)
    )
);
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);

// 获取接口返回结果中的token值, 并传给播放器播放加密视频
$token = json_decode($result)->data->token;
echo $token;

Java SpringMvc代码:

@ResponseBody
@RequestMapping("/playerSafe")
public String playerSafe(HttpServletRequest request) {
    String userId = "your userId";       // 保利威点播账号的userId
    String secretkey = "your secretkey";     // 保利威点播账号的secretkey
    String videoId = "88083abbf5bcf1356e05d39666be527a_8";  // 视频vid
    long ts = System.currentTimeMillis();      // 时间戳
    String viewerIp = getClientIp(request);  // 观众ip
    String viewerId = "12345";      // 观众id
    String viewerName = "testUser";  // 观众昵称, 若值为中文需要urlencode('张三')
    String extraParams = "HTML5";  // 自定义扩展参数
    boolean disposable = false; // true 表示 token 仅一次有效。false 则表示在有效期内可以多次验证。默认为 false。

    /* 将参数 userId、secretkey、videoId、ts、viewerIp、viewerIp、viewerId、viewerName、extraParams按照ASCKII升序 key + value + key + value ... +value 拼接
     */
    String concated = "extraParams" + extraParams + "ts" + ts + "userId" + userId + "videoId" + videoId + "viewerId" + viewerId + "viewerIp" + viewerIp + "viewerName" + viewerName;
    // 首尾加上secretkey值
    String plain = secretkey + concated + secretkey;
    // 取大写MD5,可自行选择md5库
    String sign = md5Hex(plain).toUpperCase();

    // 然后将下列参数用post请求  https://hls.videocc.net/service/v1/token 获取 token
    String url = "https://hls.videocc.net/service/v1/token";

    Map<String, String> params = new HashMap<>();
    params.put("userId", userId);
    params.put("videoId", videoId);
    params.put("ts", String.valueOf(ts));
    params.put("viewerIp", viewerIp);
    params.put("viewerName", viewerName);
    params.put("extraParams", extraParams);
    params.put("viewerId", viewerId);
    params.put("sign", sign);
    // 可自行选择http客户端
    String response = HttpClientUtil.getInstance().sendHttpPost(url, params);

    try {
        //解析json
        ObjectMapper objectMapper = new ObjectMapper();
        TokenResponse tokenResponse = objectMapper.readValue(response, TokenResponse.class);
        // 响应代码,200为成功,403为ts过期或签名错误,400为参数错误(例如缺少 userId 或 videoId)
        if (tokenResponse.getCode() == 200) {
            Map data = (Map) tokenResponse.getData();
            return data.get("token").toString();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "";
}
static class TokenResponse {
    int code;
    String status;
    String message;
    Object data;
    //省略getter、setter...
}
public String getClientIp(HttpServletRequest request) {
    String ip = request.getHeader("x-forwarded-for");
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getRemoteAddr();
    }
    return ip;
}

4.用户ID跑马灯

  图:用户ID跑马灯

将用户I的ID、电话号码或其他信息内容等设置在视频上不规则跑动(作追溯盗版者用)。 ID跑马灯功能,是指通过设定文字内容(一般是观众的身份ID信息)在视频上不规则滚动,以此来警示盗版者,达到视频版权保护的效果,示例中是将用户的ID和电话号码显示出来。

5.数字化动态水印

  图:数字化动态水印

 将用户ID、电话号码或其他信息内容等以动态水印形式展现在视频上,实现水印在视频上不规则地显现,可追溯录屏者身份,对翻录行为起到强有力的震慑作用。

6.浏览器防录屏

 图 / 浏览器防录屏

通过播放器实时监测,如果检测到视频处于录屏状态或小窗待录屏状态,视频会立即停止播放,显示报错信息,视频无法继续播放。

7.视频水印 (企业LOGO)

在视频中添加企业专属的视频水印,从而让视频中融入企业的版权信息,防止盗录者盗取版权,保护公司的知识产权。视频上传后自动将企业的LOGO图标水印加在视频右上角/右下角等位置上。

8.域名白名单​OVP防盗链

通过OVP防盗链技术实现指定网站播放,俗称域名黑白名单。设置网站A白名单,则只允许视频在A网站下播放;设置网站B黑名单,则禁止视频在B网站下播放,可有效防止用户原创视频资源被非法盗用。

9.ATS/HTTPS数据防篡改

HTTPS协议,采用了HTTPS协议,其提供网站身份验证与加密通讯方法,避免信息截韧“钓鱼”攻击,有效防止网页被篡改,保证企业及学员间的信息 安全;ATS标准,苹果操作系统遵循ATS标准,开启ATS安全特性后,网络传输自动通过HTTPS协议进行传输,保证视频播放安全。

10.播放器代码混淆加密

播放器代码加密,防反编译、代码混淆等方式。

11.禁止拖动视频进度条

html5播放器禁止拖拽功能实例(常用于场景:企业培训、在线教学内容禁止学员拖动视频进行观看)。

如果你有更多关于视频加密、视频防录、视频版权保护方面的想法,欢迎在评论区留言与大家一起分享。

  我的文章推荐:

  • [视频+图文] 线上研讨会是什么,企业对内对外培训可以用线上研讨会吗?
  • [图文] 企业直播对网络带宽有什么要求?
  • [图文]OBS如何实现毫秒级超低延时直播
  • 直播播放器API(播放器调用方法、参数、接口和事件)
  • 企业内训课程视频加密防下载是如何做的?10种思路
  • 超低延迟/无延迟直播(PRTC Web SDK移动端)兼容性说明
  • html5视频播放器代码调用实例(视频切换\倍速切换)
  • 企业直播要如何做?硬件设备、网络环境有哪些要求?
  • 企业内训课程视频加密防下载是如何做的?10种思路

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/617972.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ArcGIS Pro二次开发】(34):从字符串中提取中文、英文、数字与特殊符号

这是一个基于字段计算的工具。 有时候我们会遇到一些混杂着各种中文、英文、数字、特殊符号的文字&#xff0c;这个工具的目的是从这些复杂文字中提取出想要的特定文字。 比如说从CAD测绘图中可以读取到类似【混3】、【砖2】的文字&#xff0c;如果想要从中提取出层数或结构&…

chatgpt赋能python:Python宏变量——简介

Python宏变量——简介 Python是一种高级编程语言&#xff0c;具有易学易用、简洁清晰等优点。但我们在编写代码的时候&#xff0c;有时需要用到常量或者宏定义&#xff0c;这就需要用到宏变量。在Python中&#xff0c;宏变量是一种常见的编程方法&#xff0c;本文将详细介绍Py…

chatgpt赋能python:Python安装后怎么使用?

Python安装后怎么使用&#xff1f; Python是一种高级编程语言&#xff0c;被广泛用于Web开发、数据分析、人工智能和自动化等领域。下面我们将介绍安装Python后如何使用它。 步骤1 - 安装Python 首先&#xff0c;从官方网站下载并安装Python。在安装过程中&#xff0c;您可以…

chatgpt赋能python:Python中的构造方法是什么?

Python中的构造方法是什么&#xff1f; 当你开始学习 Python 编程时&#xff0c;你可能经常听到 “构造方法” 这个词。那么&#xff0c;什么是构造方法&#xff1f;为什么它在 Python 中很重要&#xff1f;本文将为您揭示构造方法的概念以及它们在 Python 中的作用。 什么是…

案例36:基于Springboot药店管理系统开题报告设计

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

chatgpt赋能python:Python程序员必知的Geany配置技巧

Python程序员必知的Geany配置技巧 如果你是一名Python程序员&#xff0c;并且正在寻找一个简单易用的代码编辑器&#xff0c;那么Geany是一个非常不错的选择。Geany是一款轻量级的集成开发环境&#xff08;IDE&#xff09;&#xff0c;除了Python&#xff0c;还支持许多其他编…

chatgpt赋能python:Python安装完后如何打开

Python安装完后如何打开 Python是一种高级的、解释性、交互式的编程语言&#xff0c;已经成为了广泛的编程应用领域中不可或缺的一部分&#xff0c;如网络编程、数据科学和人工智能等。Python的安装对于学习、开发和应用Python技术非常重要&#xff0c;但安装了Python后如何打…

案例38:基于Springboot电影评论网站开题报告设计

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

chatgpt赋能python:Python中的Gevent:安装和使用

Python 中的 Gevent: 安装和使用 Gevent 是 Python 生态系统中的一个流行的高性能网络库&#xff0c;它是基于 libev 的 Python 网络库&#xff0c;提供了非阻塞IO、协程和并发编程等方面的特性。Gevent 使得开发高性能的网络应用程序变得简单而易行。本文将介绍如何在 Python…

【Leetcode】78 子集 | 保存遍历路径上的所有节点 // 46 排列 | 使用辅助数组记录元素是否使用

78 子集 与组合问题相比&#xff0c;需要保存路上经过的所有节点。 写法1 分为选择第 i i i个元素和不选择第 i i i个元素两种情况递归。 每push进一个元素&#xff0c;代表进入了一个新的节点&#xff0c;就保存当前的路径。 import java.util.ArrayList; import java.uti…

JUC基础-0606

9.ReentrantReadWriteLock读写锁 9.1 锁的基本概念 悲观锁&#xff1a;不支持并发&#xff0c;效率低&#xff0c;但是可以解决所有并发安全问题 乐观锁&#xff1a;支持并发读&#xff0c;维护一个版本号&#xff0c;写的时候比较版本号进行控制&#xff0c;先提交的版本号…

chatgpt赋能python:Python配置指南:提高SEO效果的关键

Python配置指南&#xff1a;提高SEO效果的关键 Python作为一种高效、易学易用的编程语言&#xff0c;在数据科学、机器学习、网络编程等领域得到了广泛应用。作为一个网站管理员&#xff0c;如何让Python支持的应用程序尽可能地符合搜索引擎优化&#xff08;SEO&#xff09;的…

UI自动化测试之Jenkins配置

团队下半年的目标之一是实现自动化测试&#xff0c;这里要吐槽一下&#xff0c;之前开发的测试平台了&#xff0c;最初的目的是用来做接口自动化测试和性能测试&#xff0c;但由于各种原因&#xff0c;接口自动化测试那部分功能整个废弃掉了&#xff0c;其中和易用性有很大关系…

chatgpt赋能python:Python安装教程:一步步实现Python开发环境搭建

Python安装教程&#xff1a;一步步实现Python开发环境搭建 Python是一种高效、易读、易维护的编程语言。在人工智能、数据科学、Web开发等领域都有广泛的应用。如果你是一名初学者或Python开发者&#xff0c;本文将为你提供Python安装教程。 第一步&#xff1a;下载Python安装…

深入浅出之Docker Compose详解

目录 1.Docker Compose概述 1.1 Docker Compose 定义 1.2 Docker Compose产生背景 1.3 Docker Compose 核心概念 1.4 Docker Compose 使用步骤 1.5 Docker Compose 常用命令 2. Docker Compose 实战 2.1 Docker Compose下载和卸载 2.2 Docker Compose 项目概述 2.3 Do…

chatgpt赋能python:Python定义局部变量的方法

Python定义局部变量的方法 Python是一种非常流行的编程语言&#xff0c;它被广泛用于各种应用程序开发、数据科学和机器学习任务。在Python中&#xff0c;如何定义局部变量是一个非常基本的概念。本文将重点介绍Python中定义局部变量的方法。 什么是局部变量&#xff1f; 在…

前端小项目基础版本----时刻监听audio音频的声音高低 可视化显示+源码

目录 时刻监听audio音频的声音高低第一代实现:基本第二代实现:完善 时刻监听audio音频的声音高低 前端小项目基础----时刻监听audio音频的声音高低 可视化显示 第一代实现:基本 实现的效果 根据 音频的某时刻高低 调整生成不同的柱状 以下就是 源码 直接复制粘贴 找个音频放…

AIGC技术研究与应用 ---- 下一代人工智能:新范式!新生产力!(2.3-大模型发展历程 之 图像、视频生成与视觉大模型)

文章大纲 GAN 模型与强化学习强化学习生成式对抗网络 ( Generative Adversarial Nets, GAN)VAE扩散模型扩散逆扩散参考文献与学习路径GPT 系列模型解析前序文章模型进化券商研报陆奇演讲强化学习生成模型多模态GAN 模型与强化学习 强化学习 Reinforcement learning (RL) is …

【SpinalHDL快速入门】4.5、复合类型之Bundle

文章目录 1.1、描述1.2、声明1.2.1、条件信号&#xff08;Conditional signals&#xff09; 1.3、运算符1.3.1、比较&#xff08;Comparison&#xff09;1.3.2、类型转换&#xff08;Type cast&#xff09;1.3.3、将比特转换回 Bundle 1.4、IO元素方向1.4.1、in/out1.4.2、mast…

《.NET 下最快比较两个文件内容是否相同》之我的看法验证

我对文件对比这一块还是比较感兴趣的&#xff0c;也想知道哪种方式性价比最高&#xff0c;效率最好&#xff0c;所以&#xff0c;根据这篇文章&#xff0c;我自己也自测一下&#xff0c;顺便留出自己对比的结果&#xff0c;供大佬们参考一二。 大致对比方案 我这边根据文章里…