hls.js 播放音视频切片鉴权问题

<template>
  <div>
    <audio ref="audioPlayer" controls />
    <button @click="playAudio">播放音频</button>
  </div>
</template>

<script setup lang="ts">
import Hls from 'hls.js';
import { ref, onMounted, onBeforeUnmount } from 'vue';

const audioPlayer = ref<HTMLAudioElement | null>(null);

const audioUrl = 'https://pep-file.oss-cn-beijing.aliyuncs.com/zjOutResource/xxx/6101/8_b1_16/8_b1_16.m3u8?auth_key=xx';

const playAudio = () => {
  if (audioPlayer.value) {
    if (Hls.isSupported()) {
      const hls = new Hls();
      hls.loadSource(audioUrl);
      hls.attachMedia(audioPlayer.value);
      hls.on(Hls.Events.MANIFEST_PARSED, () => {
        audioPlayer.value?.play(); 
      });
    } else {
      audioPlayer.value.src = audioUrl; 
      audioPlayer.value.addEventListener('loadedmetadata', () => {
        audioPlayer.value?.play(); 
      });
    }
  }
}

onMounted(() => {
  audioPlayer.value?.load();
})

onBeforeUnmount(() => {
  if (audioPlayer.value) {
    audioPlayer.value.src = ''; 
  }
})
</script>

<style scoped>
</style>

问题:
音频路径audioUrl需要鉴权才能访问,但是m3u8里面的hls.key和.ts文件如何实现自动鉴权

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:8
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="hls.key",IV=0x6b75eb391048f9416d3a475499489390
#EXTINF:7.274833,
part_0000.ts
#EXT-X-ENDLIST
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 10

一般都是后端创建一个限时url返回前台,比如限时一天有效期

1个月前 评论
Shine-x (楼主) 1个月前

我之前是用nginx的internal限制的

写个video.php的处理脚本

<?php

/**
 * 访问 /video.php 则实际访问的是 /videos/test.mp4.
 *
 * 由此,可以在 php 里实现复杂的认证逻辑比如播放次数、ip、登录权限、用户身份等等。
 */

//TODO 做一些判断和限制


//最后跳转到资源
header("X-Accel-Redirect: /videos/test.mp4");

nginx 收到调整资源/videos/test.mp4的请求

location /videos {
     internal; 
     root /nas/videos;
}

前端直接src读video.php,video.php怎么加参数都可以

1个月前 评论
xiucai 1个月前
唐章明

如果你的意思是指文件不能公开访问(比如对象存储储存桶私有),生成了m3u8文件的签名链接,但是m3u8文件里面指向的ts切片却没有携带签名。

  • 方案1:公有云自带处理方案。
    比如阿里云,使用hls/sign签名边转边播,OSS对音视频数据的访问提供了动态签名机制,即只需在首次访问m3u8文件时在URL中添加x-oss-process=hls/sign,live_1, OSS将对返回的播放列表中的所有ts地址自动按照与m3u8完全相同的方式进行签名
    help.aliyun.com/zh/oss/user-guide/...
    developer.qiniu.com/kodo/kb/1339/i...

    原始m3u8内容

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:10
    #EXT-X-MEDIA-SEQUENCE:0
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXTINF:10.0,
    media-c14709808479b31566b50f2f8b93fe1a-0.ts
    #EXTINF:10.0,
    media-c14709808479b31566b50f2f8b93fe1a-1.ts
    #EXTINF:10.0,
    media-c14709808479b31566b50f2f8b93fe1a-2.ts
    #EXTINF:10.0,
    media-c14709808479b31566b50f2f8b93fe1a-3.ts
    #EXT-X-ENDLIST

    使用hls/sign签名后返回的内容

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:10
    #EXT-X-MEDIA-SEQUENCE:0
    #EXT-X-PLAYLIST-TYPE:VOD
    #EXTINF:10.000,
    media-c14709808479b31566b50f2f8b93fe1a-0.ts?x-oss-process=if_status_eq_404{hls/ts,from_b3V0cHV0L21lZGlhLm0zdTg}&x-oss-expires=1710457284&x-oss-signature-version=OSS2&x-oss-access-key-id=****fEAub****&x-oss-signature=****VR3gy****
    #EXTINF:10.000,
    media-c14709808479b31566b50f2f8b93fe1a-1.ts?x-oss-process=if_status_eq_404{hls/ts,from_b3V0cHV0L21lZGlhLm0zdTg}&x-oss-expires=1710457284&x-oss-signature-version=OSS2&x-oss-access-key-id=****fEAub****&x-oss-signature=****VR3gy****
    #EXTINF:10.000,
    media-c14709808479b31566b50f2f8b93fe1a-2.ts?x-oss-process=if_status_eq_404{hls/ts,from_b3V0cHV0L21lZGlhLm0zdTg}&x-oss-expires=1710457284&x-oss-signature-version=OSS2&x-oss-access-key-id=****fEAub****&x-oss-signature=****VR3gy****
    #EXTINF:10.000,
    media-c14709808479b31566b50f2f8b93fe1a-3.ts?x-oss-process=if_status_eq_404{hls/ts,from_b3V0cHV0L21lZGlhLm0zdTg}&x-oss-expires=1710457284&x-oss-signature-version=OSS2&x-oss-access-key-id=****fEAub****&x-oss-signature=****VR3gy****
    #EXT-X-ENDLIST

    其他云自行查阅文档,部分公有云的对象存储是没有这个功能的

  • 方案2:自行处理
    我刚好有使用这个功能,仅供参考

<?php


$s3 = new Aws\S3\S3Client([
    'version' => 'latest',
    'region' => 'us-east-1',
    'endpoint' => 'xxxxx',
    'credentials' => [
        'key'    => '',
        'secret' => '',
    ]
]);


try {
    $file = $s3->getObject([
        'Bucket' => 'wodevideo',
        'Key' => 'ddd2/index.m3u8',
    ]);
    $body = $file->get('Body');
    $body->rewind();

    $content = $body->getContents();


} catch (Exception $exception) {
    echo "Failed to download  from  with error: " . $exception->getMessage();
    exit("Please fix error with file downloading before continuing.");
}



// m3u8处理
$m3u8texts = explode("\n", $content);
$m3u8text = '';
foreach ($m3u8texts as $line => $lineText) {
    if( str_starts_with($lineText, '#') ){
        $m3u8text .= $lineText . "\n";
        continue;
    }

    try {
        // 把m3u8的每个ts切片转换为签名链接
        $request = $s3->createPresignedRequest($bucket, $lineText, '+10 minutes');
        $m3u8text .= $request->getUri() . "\n";

    } catch (\Exception $e) {
        // echo $e->getMessage();exit;
    }
}


// 作为m3u8文件输出
header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Headers:*");
header("Access-Control-Allow-Methods:*");
 header('Access-Control-Allow-Headers:Authorization,lpy');

header('Content-Type: application/vnd.apple.mpegurl');
header('Content-Disposition: attachment; filename="playlist.m3u8"');
echo $m3u8text;
1个月前 评论
唐章明 (作者) 1个月前
Shine-x (楼主) 1个月前
唐章明 (作者) 1个月前
唐章明 (作者) 1个月前

之前用七牛的两种方案是:

  1. 联系七牛云忽略ts切片的鉴权
  2. 将m3u8获取方式改成通过api获取 api解析m3u8 给每个ts切片做鉴权处理
1个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!