You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用变量替代stream.key文件定义HLS流密钥?如何外部指定密钥位置?

问题描述

我用FFmpeg加密MP4视频后,生成了stream.m3u8播放列表、stream.m3u8.key密钥文件和若干.ts分片文件。直接通过本地路径加载stream.m3u8的代码能正常播放:

<head>
    <link href="https://vjs.zencdn.net/7.4.1/video-js.css" rel="stylesheet">
    <script src="https://vjs.zencdn.net/7.4.1/video.min.js"></script>
</head>
<body>
    <video id="example-video" class="video-js vjs-default-skin" controls="controls" width="640" height="360">
       <source src="./stream.m3u8" type="application/x-mpegURL" />
    </video>
    <script>
        var player = videojs('example-video');
    </script>
</body>

但用<input>文件选择功能加载stream.m3u8时,播放器能识别视频时长却无法播放——因为播放列表里定义的密钥文件路径无法被本地文件URL(blob:协议)正确解析,密钥加载失败。相关代码:

<html>
    <head>
        <link href="https://vjs.zencdn.net/7.4.1/video-js.css" rel="stylesheet">
        <script src="https://vjs.zencdn.net/7.4.1/video.min.js"></script>
    </head>

    <body>
        <label for="input">Choose a video file to process:</label>
        <input type="file" id="input" name="input_video">
        <p id="demo"><p/>
        <video id="video" class="video-js vjs-default-skin" width="320" height="240" controls style="display: none;">
            <source id="vid" type="application/x-mpegURL" />
        </video>
    </body>
    
    <script>
        document.getElementById("input").addEventListener("change", function() {
          var media = URL.createObjectURL(this.files[0]);
          
          var vid = document.getElementById("vid");
          vid.src = media;
          
          var video = document.getElementById("video");
          video.style.display = "block";
          video.play();
          
          document.getElementById("demo").innerHTML = vid.src;
          
          var player = videojs('video');
          //player.play();
        });
    </script>

</html>

需要解决两个问题:

  • 如何在播放列表外部(比如JS代码中)定义密钥文件位置?
  • 能否用变量替代stream.key文件来读取和定义HLS流密钥?
解决方案

1. 在播放列表外部定义密钥文件位置

Video.js依赖的HLS处理逻辑支持通过自定义密钥加载器,拦截并替换密钥请求路径,强制使用你指定的密钥文件:

实现代码

document.getElementById("input").addEventListener("change", async function() {
  // 新增密钥文件选择逻辑
  const keyFile = await new Promise(resolve => {
    const keyInput = document.createElement('input');
    keyInput.type = 'file';
    keyInput.accept = '.key';
    keyInput.onchange = () => resolve(keyInput.files[0]);
    keyInput.click();
  });

  const mediaUrl = URL.createObjectURL(this.files[0]);
  const keyUrl = URL.createObjectURL(keyFile);

  const vid = document.getElementById("vid");
  vid.src = mediaUrl;

  const video = document.getElementById("video");
  video.style.display = "block";

  const player = videojs('video');
  
  // 播放器就绪后替换密钥加载逻辑
  player.ready(() => {
    const hls = player.tech({ IWillNotUseThisInPlugins: true }).hls;
    
    hls.keyLoader = function(hls, uri) {
      // 忽略播放列表中的密钥路径,使用用户选择的密钥文件
      return fetch(keyUrl)
        .then(response => response.arrayBuffer())
        .then(buffer => new Uint8Array(buffer));
    };
  });
});

2. 使用变量替代密钥文件

完全可以直接用变量存储密钥内容,不需要依赖本地密钥文件。只要能拿到密钥的二进制数据,就能在密钥加载器中直接返回:

示例代码

场景1:已知密钥二进制数据

// 替换为你的真实密钥二进制数据
const keyData = new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef]);

document.getElementById("input").addEventListener("change", function() {
  const mediaUrl = URL.createObjectURL(this.files[0]);
  const vid = document.getElementById("vid");
  vid.src = mediaUrl;

  const video = document.getElementById("video");
  video.style.display = "block";

  const player = videojs('video');
  
  player.ready(() => {
    const hls = player.tech({ IWillNotUseThisInPlugins: true }).hls;
    
    hls.keyLoader = function(hls, uri) {
      // 直接返回预定义的密钥变量
      return Promise.resolve(keyData);
    };
  });
});

场景2:密钥为字符串格式

如果密钥是字符串,先转成Uint8Array再使用:

const keyString = "your-real-key-string";
const keyData = new TextEncoder().encode(keyString);
关键说明
  • 当使用URL.createObjectURL加载本地m3u8时,播放器处于blob:协议环境,无法直接访问本地文件系统的密钥文件,必须通过自定义加载逻辑绕过限制。
  • 自定义密钥加载器可以根据uri参数做精细匹配,支持多密钥场景下的针对性替换。

内容的提问来源于stack exchange,提问作者Saeed Eisakhani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:05:19