ffmpeg视频转切片m3u8并加密videojs播放hls.js播放dplayer播放(弹幕效果)

news2024/11/14 21:51:05

文章目录

  • 学习链接
  • 步骤
    • 安装openssl
    • 生成一个enc.key文件
    • 生成加密串
    • 创建enc.keyinfo文件
    • 视频切分
      • m3u8文件
    • web前端查看m3u8视频
      • 后台返回enc.key的接口
      • videojs播放m3u8视频
    • 其它
      • videojs切换播放视频
      • hls.js切换播放视频
      • dplayer切换播放视频(弹幕)

学习链接

Java实现视频加密及播放

使用ffmpeg视频切片并加密

mp4视频分片生成m3u8流文件并加密

html中 videojs 播放m3u8文件【方式一】
html中 DPlayer 播放m3u8文件【方式二】

vue播放播放M3U8格式——HLS的直播流

Vue Video.js播放m3u8视频流格式(video+videojs-contrib-hl)

vue中使用video标签播放MP4,m3u8格式视频

步骤

安装openssl

参考:Security OAuth2 授权 & JWT 中安装openssl部分、安装OpenSSL

下载 openssl安装包,一般下载列表第1个EXE即可(不带light的是完整功能的安装包,我们用不到),下载完成后双击安装一直点下一步就行了。在这里插入图片描述
配置环境变量,老生常谈,openssl的默认安装路径为C:\Program Files\OpenSSL-Win64\bin,这里有windows配置环境变量的通用教程,最后我们验证下是否配置成功openssl -v 或者 openssl version。

在这里插入图片描述

centos7安装openssl:sudo yum install pcre-devel openssl openssl-devel -y

生成一个enc.key文件

生成一个enc.key文件,license与windows指令相同
在这里插入图片描述

生成加密串

生成加密串(b6dc7333568a0deef8e6b331b9725264),记下来
在这里插入图片描述

创建enc.keyinfo文件

新建一个文件 enc.keyinfo 内容格式如下:

Key URI            # enc.key的路径,使用http形式
Path to key file   # enc.key文件
IV                 #  上面生成的iv

示例

http://localhost/video/enc.key
enc.key
b6dc7333568a0deef8e6b331b9725264

在这里插入图片描述

视频切分

视频切分,传一个test.mp4到enc.key路径下,通过黑窗口执行下面的指令

ffmpeg -y  -i test.mp4 -hls_time 12  -hls_key_info_file enc.keyinfo  -hls_playlist_type vod  -hls_segment_filename "file%d.ts"  playlist.m3u8
  • 解释
    ffmpeg -y \
    
    -i test.mp4 \
    
    -hls_time 12 \                       # 将test.mp4分割成每个小段多少秒
    
    -hls_key_info_file enc.keyinfo \
    
    -hls_playlist_type vod \             # vod 是点播,表示PlayList不会变
    -hls_segment_filename "file%d.ts" \  #  每个小段的文件名
    
    playlist.m3u8                        #  生成的m3u8文件
    

在这里插入图片描述

m3u8文件

这个URI路径可以修改,只要能返回enc.key的数据就行了

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:50
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="http://localhost/video/enc.key",IV=0xb6dc7333568a0deef8e6b331b9725264
#EXTINF:50.000000,
file0.ts
#EXTINF:50.000000,
file1.ts
#EXTINF:14.600000,
file2.ts
#EXT-X-ENDLIST

web前端查看m3u8视频

后台返回enc.key的接口

在这里插入图片描述

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
                .addMapping("/**")
                .maxAge(3600)
                .allowCredentials(true)
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .exposedHeaders("token","Authorization")
        ;
    }

}

videojs播放m3u8视频

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>videojs-contrib-hls embed</title>
    <!--
    Uses the latest versions of video.js and videojs-contrib-hls.
    To use specific versions, please change the URLs to the form:  
    -->

  <link href="https://unpkg.com/video.js@5.16.0/dist/video-js.css" rel="stylesheet">
  <script src="https://unpkg.com/video.js@5.16.0/dist/video.js"></script>
  <script src="https://unpkg.com/videojs-contrib-hls@4.1.1/dist/videojs-contrib-hls.js"></script>


  
  
</head>
<body>
  <h1>Video.js Example Embed</h1>

  <video id="my_video_1" 
         class="video-js vjs-default-skin" 
         controls preload="auto" width="640" height="268" 
         data-setup='{}'>
    <source 
         src="./video/playlist.m3u8" type="application/x-mpegURL">
  </video>
  
  
</body>
</html>

当未提供enc.key的文件时,报错
在这里插入图片描述
直接修改m3u8的URI也是没问题的,只要后台改了就行
在这里插入图片描述

其它

videojs切换播放视频

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>videojs-contrib-hls embed</title>
    <!--
    Uses the latest versions of video.js and videojs-contrib-hls.
    To use specific versions, please change the URLs to the form:  
    -->

  <link href="https://unpkg.com/video.js@5.16.0/dist/video-js.css" rel="stylesheet">
  <script src="https://unpkg.com/video.js@5.16.0/dist/video.js"></script>
  <script src="https://unpkg.com/videojs-contrib-hls@4.1.1/dist/videojs-contrib-hls.js"></script>


  
  
</head>
<body>
  <h1>Video.js Example Embed</h1>

  <video id="my_video_1" 
         class="video-js vjs-default-skin" 
         controls preload="auto" width="640" height="268" 
         data-setup='{}'>
    <source  src="./video1/playlist.m3u8" type="application/x-mpegURL">
  </video>

  <hr>

  <button id="video1" onclick="videoHandler(event)" data-videourl="./video1/playlist.m3u8">视频1</button>
  <button id="video2" onclick="videoHandler(event)" data-videourl="./video2/index.m3u8">视频2</button>
  <button id="video3" onclick="videoHandler(event)" data-videourl="http://devimages.apple.com/iphone/samples/bipbop/gear1/prog_index.m3u8">失效的url</button>
  <button onclick="pause()">暂停</button>
  <button onclick="play()">播放</button>
  <button onclick="destroy()">关闭</button>
  
  <script>
    const playerOptions = {
        autoplay: false, // 自动播放
        controls: true, // 显示控制条
        errorDisplay: false, // 隐藏错误提示
        muted: true, // 静音
        sources: [
          {
            // src: "./video1/playlist.m3u8",
            src: "./video2/index.m3u8",
            type: "application/x-mpegURL",
          },
        ],
      };

      var player = videojs(document.querySelector('#my_video_1'), playerOptions, () => {
        console.log("Video.js player is ready");
      })

      function videoHandler(e) {
        const videoUrl = e.target.dataset.videourl;
        player.src({
          src: videoUrl,
          type: "application/x-mpegURL",
        });
        player.load(); // 重新加载视频
        // player.play(); // 
        
      }


      player.on("error", (event) => {
        console.error("Error:", event.error);
        player.src({
          src: './video2/index.m3u8',
          type: "application/x-mpegURL",
        });
      });

      player.on("play", (event) => {
        console.log('play', event); // 开始播放和每次点击播放进度条时都会触发
      });

      player.on("ended", (event) => {
        console.log('ended', event); // 播放结束
      });

      function pause() {
        player.pause(); // 暂停
      } 

      function play() {
        player.play(); // 继续播放
      }

      function destroy() {
        player.dispose(); // 关闭 , video这个dom都被删除了
        player = null
      }

  </script>
  
</body>
</html>

hls.js切换播放视频

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>

<body>
    <video id="video" width="640" height="268" controls></video>
    <hr />
    <button id="video1" onclick="videoHandler(event)" data-videourl="./video1/playlist.m3u8">视频1</button>
    <button id="video2" onclick="videoHandler(event)" data-videourl="./video2/index.m3u8">视频2</button>
    <button onclick="playVideo()">播放</button>
    <button onclick="pauseVideo()">暂停</button>
</body>
<script>
    var video = document.getElementById('video');
    if (Hls.isSupported()) {

        // 可参考: 
        // hls的github文档中的api:(https://github.com/video-dev/hls.js/blob/master/docs/API.md)
        // hls.js如何播放m3u8文件(实例)?(https://blog.csdn.net/ffffffff8/article/details/129314268)
        // Vue 之 视频流 - Hls.js(https://blog.csdn.net/a15297701931/article/details/115478652)
        let config = {
            xhrSetup: function (xhr, url) {
                xhr.withCredentials = true; // 会携带cookie
                // 在请求http://127.0.0.1:5500/video2/index.m3u8时会携带token请求头
                // 在请求http://127.0.0.1:5500/video2/index000.ts时会携带token请求头
                xhr.setRequestHeader('token', "my-token")
            },
        }
        var hls = new Hls(config);

        hls.on(Hls.Events.MANIFEST_PARSED, function () {
            console.log('MANIFEST_PARSED');
            // video.play(); // Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD
        });

        hls.loadSource('./video2/index.m3u8');
        hls.attachMedia(video);

        function playVideo() {
            video.play()
        }

        function pauseVideo() {
            video.pause()
        }

        function videoHandler(e) {
            console.log(e.target.dataset.videourl);
            hls.loadSource(e.target.dataset.videourl);
            hls.attachMedia(video);
        }
    }
    // HLS.js is not supported on platforms that do not have Media Source
    // Extensions (MSE) enabled.
    //
    // When the browser has built-in HLS support (check using `canPlayType`),
    // we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video
    // element through the `src` property. This is using the built-in support
    // of the plain video element, without using HLS.js.
    else if (video.canPlayType('application/vnd.apple.mpegurl')) {
        video.src = videoSrc;
    }


</script>

</html>

dplayer切换播放视频(弹幕)

  1. 可以切换视频,可以发送弹幕(发送完弹幕后,可以在本地显示,可以调用dp.danmaku.send(danmaku, callback: function): 提交一个新弹幕,后面可以使用websoket将代码发到其它观看此视频的用户)

  2. 必须引入DPlayer.min.css,否则弹幕无法正常显示

  3. 有个问题:按照官网设置的danmaku的token,但是在请求弹幕接口的时候没有携带这个请求头,不知道该问题的原因(哦,原来是发送弹幕的时候,会携带这个danmaku.token参数到Request Payload中,我还以为请求弹幕的时候,也得带呢)

  4. 弹幕的格式:每条弹幕都是1个数组,数组中按顺序依次是:time-时间,type-类型,color-颜色,author-发送者,text-内容

  5. 弹幕返回的示例可以参考,https://s-sh-17-dplayercdn.oss.dogecdn.com/1678963.json

    {
        "code": 0,
        "data": [
            [
                230.523,
                0,
                16777215,
                "618c713c",
                "键盘妹子挺好看?"
            ],
            [
                25.837,
                0,
                16777215,
                "6b2884ac",
                "Goose house炒鸡棒!!!  银之匙种草他们组合"
            ],
            [
                235.243,
                1,
                16707842,
                "929815d3",
                "刚才说比其他翻唱都好听的你是认真的么,这。就是原唱"
            ],
            [
                86.841,
                0,
                16777215,
                "6f30afd1",
                "喜欢短发的"
            ]
        ]
    }
    

在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            margin: 0;
        }

        .dplayer-container {
            width: 800px;
            height: 500px;
            border: 5px solid red;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        #dplayer {
            width: 100%;
            height: 100%;
            object-fit: cover;
            border: 5px solid black;
        }
    </style>
    <!-- <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.js"></script> -->
    <link rel="stylesheet" href="./css/DPlayer.min.css">
    <script src="./js/hls.js"></script>
    <script src="./js/dplayer.js"></script>
</head>

<body>

    <div class="dplayer-container">
        <div id="dplayer"></div>
    </div>

    <hr />

    <button id="video1" onclick="videoHandler(event)" data-videourl="./video1/playlist.m3u8">视频1</button>
    <button id="video2" onclick="videoHandler(event)" data-videourl="./video2/index.m3u8">视频2</button>
    <button onclick="playVideo()">播放</button>
    <button onclick="pauseVideo()">暂停</button>

    <script>
        // 另一种方式,使用 customType
        const dp = new DPlayer({
            container: document.getElementById('dplayer'),
            autoplay: false, // 自动播放

            video: {
                url: './video1/playlist.m3u8',
                type: 'customHls',
                pic: './soft-dev.png', // video的poster属性, 视频封面
                customType: {
                    customHls: function (video, player) {
                        let config = {
                            xhrSetup: function (xhr, url) {
                                xhr.withCredentials = true; // 会携带cookie
                                xhr.setRequestHeader('token', "my-token")
                            },
                        }
                        const hls = new Hls(config);
                        hls.loadSource(video.src);
                        hls.attachMedia(video);
                    },
                },
                /* quality: [ // 清晰度
                    {
                        name: '标清哦',
                        url: './video1/playlist.m3u8',
                        type: 'customHls',
                    },
                    {
                        name: '高清哦',
                        url: './video2/index.m3u8',
                        type: 'customHls',
                    },
                ],
                defaultQuality: 0, */
            },
            volume: 1, // 默认音量
            playbackSpeed: [0.5, 1, 1.25, 1.5, 2], // 可选的播放速率,可以设置成自定义的数组
            lang: 'zh-cn', // 显示为中文
            loop: true, // 是否循环播放
            hotkey: true, // 开启热键,支持快进、快退、音量控制、播放暂停
            screenshot: true, // 开启截图功能
            theme: 'orange', // 进度条颜色
            logo: 'naughty.gif', // 左上角logo
            preventClickToggle: false, // 阻止点击播放器时候自动切换播放/暂停
            contextmenu: [ // 右键视频时的菜单
                {
                    text: 'custom1',
                    link: 'https://github.com/DIYgod/DPlayer',
                },
                {
                    text: 'custom2',
                    click: (player) => {
                        console.log(player);
                    },
                },
            ],
            highlight: [ // 视频进度条上的高亮点
                {
                    time: 20,
                    text: '这是第 20 秒',
                },
                {
                    time: 60,
                    text: '这是 1 分钟',
                },
            ],
            danmaku: {
                id: './video1/playlist.m3u8',
                user: 'user1',
                token: 'tokendemo',
                // 这个api会发送1个请求: http://localhost:82/barrage/v3/?id=./video1/playlist.m3u8
                api: 'http://localhost:82/barrage/',    //这里填写弹幕地址 liveweb
                addition: ['https://s-sh-17-dplayercdn.oss.dogecdn.com/1678963.json']
            }
        });

        dp.danmaku.token = 'tokendemo';

        // 视频切换
        function videoHandler(e) {
            console.log(e.target.dataset.videourl);
            dp.switchVideo(
                // 指定视频设置
                {
                    url: e.target.dataset.videourl,
                    pic: '',
                },
                // 指定弹幕设置
                {
                    id: e.target.dataset.videourl,
                    api: 'http://localhost:82/barrage/',
                    maximum: 3000,
                    user: 'DIYgod',
                }
            )
        }

        function playVideo() {
            dp.play()
        }

        function pauseVideo() {
            dp.pause()
        }

        Window.dp = dp;

    </script>
</body>

</html>

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

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

相关文章

redis主从同步

redis 相比于memcached可以永久缓存。 首先停掉mysql源码安装redis 1. 安装redis cd /root/redis-6.2.4 make # 直接make&#xff0c;里面已经配置过了 make install# 安装 cd utils/ ./install_server.sh需要在文件里面注释掉&#xff0c;systemd判断语句 vim install_s…

【GPT】Coze使用开放平台接口-【2】创建工作流-语音伪造检测工作流

在Coze使用开放平台接口-【1】创建插件&#xff0c;我们已经成功创建了开放平台的插件&#xff0c;也创建了对应的工具。本文档就根据创建好的插件&#xff0c;来创建对应的工作流&#xff0c;来让接口能够用起来。 下面直接用现成的插件快商通AI开放平台&#xff0c;来创建语音…

202408830使用python3给BGR3的裸图加上BMP图的文件头

202408830使用python3给BGR3的裸图加上文件头 2024/8/30 20:20 缘起&#xff0c;获取SONY索尼的8530的机芯的4K的BGR3的裸图。可以使用7-yuv打开了。 如果直接可以给这张YUV图加上BMP格式的文件头&#xff0c;就可以直接使用标准的图像处理软件/ACDSee5.0打开了&#xff01; 这…

RISC-V单片机智能落地扇方案

在众多产品中&#xff0c;智能落地扇产品凭借其出色的性能和质量优势&#xff0c;备受消费者青睐。智能落地扇有着卓越的性能和智能化的操作。 RAMSUN提供的智能落地扇方案主控单片机芯片采用RISC-V微处理器&#xff0c;内置高速存储器&#xff0c;最高工作频率可达144MHz&…

【智能算法改进】多策略融合的改进黑猩猩搜索算法及其应用

目录 1.算法原理2.改进点3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】黑猩猩优化算法&#xff08;ChOA&#xff09;原理及实现 2.改进点 改进的 Sine 混沌映射初始化种群 ChoA 种群随机初始化的方法导致种群多样性、均匀性差、容易出现边界聚集现象&#xff0c…

E30.【C语言】练习:sizeof和strlen的习题集(B)

Exercise 4:sizeof 字符串 求下列代码打印结果 #define CRT_NO_WARNINGNESS 1 #include <stdio.h> #include <string.h> int main() {char arr[] "abcdef";printf("%zd\n", sizeof(arr));printf("%zd\n", sizeof(arr 0));printf…

gitee 简单使用

目录 1. github 介绍 2. gitee 介绍 2.1 下载工具 2.2 创建仓库 2.3 clone 远程仓库到本地 2.4 上传代码 2.4.1 add:预添加到本地仓库 2.4.2 commit:提交代码到仓库 2.4.3 push:推送添加操作到远程仓库 3. 问题解决 3.1 文件推送成功&#xff0c;gitee没有绿点 3.2…

UR5e Gazebo仿真

一、环境准备 安装ROS Noetic 首先&#xff0c;确保你的Ubuntu 20.04系统已经安装了ROS Noetic。如果未安装&#xff0c;可以通过ROS的官方仓库进行安装。创建工作空间 创建一个新的ROS工作空间&#xff0c;用于存放UR5e相关的代码和配置文件。 bash复制代码 mkdir -p ~/ur5e…

Qt:玩转QPainter序列六(图形)

前言 继续看源码。 正文 剩下的大部分都是画各种图形的函数&#xff0c;它们一般都有多个重载版本&#xff0c;我就不一 一介绍使用了&#xff0c;只挑其中的一部分使用一下。 在 QPainter 类中&#xff0c;这些方法涉及到绘图的各种功能&#xff0c;主要用于设置视图变换、…

AI大模型日报#0830:智谱AI推出多款升级模型、阿里开源多模态Qwen2-VL

导读&#xff1a;AI大模型日报&#xff0c;爬虫LLM自动生成&#xff0c;一文览尽每日AI大模型要点资讯&#xff01;目前采用“文心一言”&#xff08;ERNIE-4.0-8K-latest&#xff09;、“智谱AI”&#xff08;glm-4-0520&#xff09;生成了今日要点以及每条资讯的摘要。欢迎阅…

Vue前端开发必备工具——json-server模拟后端服务器

文章目录 1、简介2、安装3、快速使用(1)创建JSON文件&#xff1a;(2) 启动json-server(3) 使用API(4) 以其它端口号启动(5) 启动多个API 当我们用Vue开发前端时&#xff0c;如果想调用后端接口&#xff0c;又没有真实的后端接口服务器怎么办&#xff1f;答案是&#xff1a;可以…

数据结构(邓俊辉)学习笔记】串 05——KMP算法:理解next[]表

文章目录 1.快速移动2.避免回溯3.通配哨兵 1.快速移动 在接下来这节&#xff0c;就让我们从严格的意义上来理解 next 表的具体含义及其原理。 我们已经切实地看到&#xff0c; KMP 算法的优化效果首先体现在它可以使模式串得以快速地后移&#xff0c;而不是如蛮力算法那样只…

jmeter连接mysql数据库以及常规用法

1、在jmeter中新建一个测试计划&#xff0c;在测试计划界面中点击浏览&#xff0c;选择连接mysql数据库的jar包 如果没有jar包可以去网上下载&#xff0c;也可以通过如下链接进行下载 链接: https://pan.baidu.com/s/1BI6f19KSzXGlkSOwbnequw 提取码: gn8e 2、然后创建线程组&a…

CentOS7安装docker小记

首先你得需要有一个虚拟机&#xff0c;我的配置如图&#xff1a; 安装docker的工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 指定阿里云的仓库 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.re…

生信机器学习入门3 - Scikit-Learn训练机器学习分类感知器

1. 在线读取iris数据集 import os import pandas as pd# 下载 try:s https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.dataprint(From URL:, s)df pd.read_csv(s,headerNone,encodingutf-8)except HTTPError:s iris.data# 读取.data文件&#xff0c;…

使用python导出Excel表格中的lua配置

背景&#xff1a;游戏开发中&#xff0c; 策划使用Excel配置游戏中的参数数据&#xff0c;写一个工具用于导出这些配置 工具选择使用 python来开发&#xff0c;这样Windows、macOS、Linux平台都可以使用&#xff0c;而且有丰富的第三方模块。 本机先安装python&#xff0c;我…

nvidia-cuda-tensorrt-cudnn下载网站

tensorrt:https://developer.nvidia.com/tensorrt/download cudnn:https://developer.nvidia.com/rdp/cudnn-archive cuda:https://developer.nvidia.com/cuda-toolkit-archive

Python编码系列—Python微服务架构:构建可扩展的云原生应用

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

积极讨论取真经 自力更生辟新径 攻克难题会有时

你是如何克服编程学习中的挫折感的&#xff1f; 编程学习之路上&#xff0c;挫折感就像一道道难以逾越的高墙&#xff0c;让许多人望而却步。然而&#xff0c;真正的编程高手都曾在这条路上跌倒过、迷茫过&#xff0c;却最终找到了突破的方法。你是如何在Bug的迷宫中找到出口的…

火绒补充

目录 为什补充&#xff1f; 用户界面优化&#xff1a; 性能提升&#xff1a; 启发式检测和行为分析&#xff1a; 恶意网址拦截&#xff1a; 系统修复功能&#xff1a; 网络安全防护&#xff1a; 云查杀引擎&#xff1a; 漏洞修复和补丁管理&#xff1a; 隐私保护&…