如图,先看看效果

 

 实现方式

1. 通过api获取视频相关m3u8地址,并进行分析(web版可通过调试模式查看)

结果如下

{
	"domain_id": "bj29",
	"drive_id": "650296441",
	"file_id": "63857a5ce3abce4520f84562b13025174c070455",
	"video_preview_play_info": {
		"category": "live_transcoding",
		"meta": {
			"duration": 1948.565,
			"width": 1920,
			"height": 804,
			"live_transcoding_meta": {
				"ts_segment": 10,
				"ts_total_count": 195,
				"ts_pre_count": 3
			}
		},
		"live_transcoding_task_list": [{
			"template_id": "SD",
			"template_name": "pdsSD",
			"template_width": 960,
			"template_height": 540,
			"status": "finished",
			"stage": "stage_all",
			"url": "https://ccp-bj29-video-preview.oss-enet.aliyuncs.com/lt/8E5DB0912CE1598D006840896CA15A958DAF92B1_272593777__sha1_bj29/SD/media.m3u8?di=bj29&dr=650296441&f=63857a5ce3abce4520f84562b13025174c070455&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5bvMt%2FTg5xZg7SpW0XIszIMaMlHuPTKuDz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNQDEHS%2FzqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABbS5XKPjPcw392n9aHLm5OsD0KUn%2Bu79doqjgQ%2B1kAmRACx4%2BIxJ0fPW4a%2Fso83ckeFioW7U%2Fg%2B9PzOSsbGXjM700r1nvfDenlXX%2B2GPOXjhd8S%2BMYi0GlJq5mZJAYNCh%2BELs8D5H45hN6DkC6aSP%2FLBmyoGipqJ9gwyK%2BxXZki8%3D&u=d636c4f1ca374695af84e6c6ea118436&x-oss-access-key-id=STS.NUZyegnCx4vBYcyW2YdFkW1aZ&x-oss-expires=1669723761&x-oss-process=hls%2Fsign&x-oss-signature=UXkAh73fYqPHxryhD5M9ZWaOnpkxSpNrFjAeWOEcVDw%3D&x-oss-signature-version=OSS2"
		}, {
			"template_id": "HD",
			"template_name": "pdsHD",
			"template_width": 1280,
			"template_height": 720,
			"status": "finished",
			"stage": "stage_all",
			"url": "https://ccp-bj29-video-preview.oss-enet.aliyuncs.com/lt/8E5DB0912CE1598D006840896CA15A958DAF92B1_272593777__sha1_bj29/HD/media.m3u8?di=bj29&dr=650296441&f=63857a5ce3abce4520f84562b13025174c070455&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5bvMt%2FTg5xZg7SpW0XIszIMaMlHuPTKuDz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNQDEHS%2FzqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABbS5XKPjPcw392n9aHLm5OsD0KUn%2Bu79doqjgQ%2B1kAmRACx4%2BIxJ0fPW4a%2Fso83ckeFioW7U%2Fg%2B9PzOSsbGXjM700r1nvfDenlXX%2B2GPOXjhd8S%2BMYi0GlJq5mZJAYNCh%2BELs8D5H45hN6DkC6aSP%2FLBmyoGipqJ9gwyK%2BxXZki8%3D&u=d636c4f1ca374695af84e6c6ea118436&x-oss-access-key-id=STS.NUZyegnCx4vBYcyW2YdFkW1aZ&x-oss-expires=1669723761&x-oss-process=hls%2Fsign&x-oss-signature=xOZom4mrmiGuALYAIMH%2Bo4ONoG%2FgaXGzFMqgx74EgoE%3D&x-oss-signature-version=OSS2"
		}, {
			"template_id": "FHD",
			"template_name": "pdsFHD",
			"template_width": 1920,
			"template_height": 1080,
			"status": "finished",
			"stage": "stage_all",
			"url": "https://ccp-bj29-video-preview.oss-enet.aliyuncs.com/lt/8E5DB0912CE1598D006840896CA15A958DAF92B1_272593777__sha1_bj29/FHD/media.m3u8?di=bj29&dr=650296441&f=63857a5ce3abce4520f84562b13025174c070455&security-token=CAIS%2BgF1q6Ft5B2yfSjIr5bvMt%2FTg5xZg7SpW0XIszIMaMlHuPTKuDz2IHFPeHJrBeAYt%2FoxmW1X5vwSlq5rR4QAXlDfNQDEHS%2FzqVHPWZHInuDox55m4cTXNAr%2BIhr%2F29CoEIedZdjBe%2FCrRknZnytou9XTfimjWFrXWv%2Fgy%2BQQDLItUxK%2FcCBNCfpPOwJms7V6D3bKMuu3OROY6Qi5TmgQ41Uh1jgjtPzkkpfFtkGF1GeXkLFF%2B97DRbG%2FdNRpMZtFVNO44fd7bKKp0lQLukMWr%2Fwq3PIdp2ma447NWQlLnzyCMvvJ9OVDFyN0aKEnH7J%2Bq%2FzxhTPrMnpkSlacGoABbS5XKPjPcw392n9aHLm5OsD0KUn%2Bu79doqjgQ%2B1kAmRACx4%2BIxJ0fPW4a%2Fso83ckeFioW7U%2Fg%2B9PzOSsbGXjM700r1nvfDenlXX%2B2GPOXjhd8S%2BMYi0GlJq5mZJAYNCh%2BELs8D5H45hN6DkC6aSP%2FLBmyoGipqJ9gwyK%2BxXZki8%3D&u=d636c4f1ca374695af84e6c6ea118436&x-oss-access-key-id=STS.NUZyegnCx4vBYcyW2YdFkW1aZ&x-oss-expires=1669723761&x-oss-process=hls%2Fsign&x-oss-signature=K5t%2Fe3zHSTVmsJNxUoVi1giCTC4sSTqM6mF5rDyYuM4%3D&x-oss-signature-version=OSS2",
			"keep_original_resolution": true
		}]
	}
}

可以看到,共有三种分辨率可选择,但是阿里云盘并没有提供 分辨率列表的m3u8文件,因此,需要我们自己实现该文件

2.通过Python读取不同分辨率下载连接,并拼接成相应的文件

def quoted(string):
    return '"%s"' % string


class StreamInfo(object):
    bandwidth = None
    program_id = None
    resolution = None
    codecs = None
    name = None

    def __init__(self, **kwargs):
        self.bandwidth = kwargs.get("bandwidth")
        self.program_id = kwargs.get("program_id")
        self.resolution = kwargs.get("resolution")
        self.codecs = kwargs.get("codecs")
        self.name = kwargs.get("name")

    def __str__(self):
        stream_inf = []
        if self.program_id is not None:
            stream_inf.append('PROGRAM-ID=%d' % self.program_id)
        if self.bandwidth is not None:
            stream_inf.append('BANDWIDTH=%d' % self.bandwidth)
        if self.resolution is not None:
            stream_inf.append('RESOLUTION=' + self.resolution)
        if self.codecs is not None:
            stream_inf.append('CODECS=' + quoted(self.codecs))

        if self.name is not None:
            stream_inf.append('NAME=' + self.name)
        return ",".join(stream_inf)


def format_m3u8_data(preview_play_info: List[LiveTranscodingTask]):
    start_str = '#EXTM3U'
    for preview in preview_play_info:
        if preview.status == 'finished':
            if preview.template_id == 'SD':
                stream_inf = StreamInfo(bandwidth=836280, program_id=1, codecs="mp4a.40.2,avc1.64001f",
                                        name=preview.template_name,
                                        resolution=f"{preview.template_width}x{preview.template_height}")
            elif preview.template_id == 'HD':
                stream_inf = StreamInfo(bandwidth=2149280, program_id=1, codecs="mp4a.40.2,avc1.64001f",
                                        name=preview.template_name,
                                        resolution=f"{preview.template_width}x{preview.template_height}")
            elif preview.template_id == 'FHD':
                stream_inf = StreamInfo(bandwidth=6221600, program_id=1, codecs="mp4a.40.2,avc1.640028",
                                        name=preview.template_name,
                                        resolution=f"{preview.template_width}x{preview.template_height}")
            else:
                stream_inf = StreamInfo(bandwidth=460560, program_id=1, codecs="mp4a.40.5,avc1.420016",
                                        name=preview.template_name,
                                        resolution=f"{preview.template_width}x{preview.template_height}")

            start_str += '\n#EXT-X-STREAM-INF:' + str(stream_inf) + '\n' + preview.url
    return start_str

def get_video_m3u8(file_obj: FileInfo, template_id='FHD|HD|SD|LD'):
    drive_obj = AliyunDrive.objects.filter(active=True, enable=True, access_token__isnull=False,
                                           pk=file_obj.aliyun_drive_id.pk).first()
    if drive_obj:
        ali_obj: Aligo = get_aliyun_drive(drive_obj)
        result = ali_obj.get_video_preview_play_info(file_id=file_obj.file_id, drive_id=file_obj.drive_id,
                                                     template_id=template_id)
        return format_m3u8_data(result.video_preview_play_info.live_transcoding_task_list[::-1])

view实现

from io import BytesIO
from wsgiref.util import FileWrapper

from django.http import FileResponse
from django.views import View

class M3U8View(View):
    def get(self, request, file_id):
        token = request.GET.get('token')
        if token and file_id and verify_token(token, file_id, success_once=False):
            instance = FileInfo.objects.filter(file_id=file_id, category='video').first()
            if instance:
                m3u8_data = get_video_m3u8(instance)
                buffer = BytesIO(m3u8_data.encode('utf-8'))
                m3u8_file = FileWrapper(buffer)
                response = FileResponse(m3u8_file)
                response['Content-Type'] = "audio/mpegurl"
                return response
        return ApiResponse(msg='error')

然后通过http接口,请求内容如下

3.前端通过vue实现,使用的是  vue3-video-play 插件

插件github: GitHub - xdlumia/vue3-video-play: 适用于 Vue3 的 hls.js 播放器组件,配置丰富,界面还算好看

 定义视屏页面

<template>
  <el-dialog v-model="showVisible" :close-on-click-modal="false" :title="videoTitle" center destroy-on-close draggable
             width="850px">
    <video-play
        :src="videoSrc"
        v-bind="videoOptions"
    />
  </el-dialog>
</template>

<script>
import 'vue3-video-play/dist/style.css'
import {videoPlay} from 'vue3-video-play'


export default {
  name: "PreviewVideo",
  data() {
    return {
      videoOptions: {
        width: "800px", //播放器高度
        height: "450px", //播放器高度
        color: "#409eff", //主题色
        title: "", //视频名称
        type: "m3u8",
        // src: "",
        muted: false, //静音
        webFullScreen: false,
        speedRate: ["0.75", "1.0", "1.25", "1.5", "2.0"], //播放倍速
        autoPlay: false, //自动播放
        loop: false, //循环播放
        mirror: false, //镜像画面
        lightOff: false, //关灯模式
        volume: 0.3, //默认音量大小
        control: true, //是否显示控制
        controlBtns: [
          "audioTrack",
          "quality",
          "speedRate",
          "volume",
          "setting",
          "pip",
          "pageFullScreen",
          "fullScreen",
        ], //显示所有按钮,
      },
    }
  },
  computed: {
    showVisible: {
      get() {
        return this.videoVisible
      },
      set(value) {
        this.$emit('update:videoVisible', value)
      }
    }
  },
  props: {
    videoVisible: {},
    videoTitle: {
      type: String,
      default: '',
    },
    videoSrc: {
      type: String,
      require: true,
    }
  }, methods: {}, watch: {}, components: {
    videoPlay
  }, mounted() {
  }
}
</script>

<style scoped>

</style>

 代码已经开源,全部代码参考 GitHub - nineaiyu/xshare: 基于阿里云盘的文件分享平台

Logo

前往低代码交流专区

更多推荐