vue3 解析直播流(flv/m3u8)

flv.js 安装

flv.js API

hls.js API 

npm install --save flv.js
npm install --save hls.js

详细使用不做介绍,自行查阅文档API,提几点注意事项:

  1. 必须在DOM加载完成后再执行直播视频流的填充方法
  2. 同时播放多个视频可能会导致性能问题,包括视频的加载时间、占用带宽和系统资源
  3. 在离开这个页面的时候必须销毁播放容器,不然会占用TCP个数,导致其他页面的监控也播放不了
<script setup>
import loadingImg from "@/assets/img/bg.png";
import flvJs from "flv.js";
import Hls from "hls.js";

const props = defineProps({
  url: {
    type: String,
    default: "",
  },
  poster: {
    type: String,
    default: loadingImg,
  },
  width: {
    type: String,
    default: "100%",
  },
  height: {
    type: String,
    default: "100%",
  },
});

const player = ref(null);
const videoElementRef = ref();
const url = computed(() => props.url);

const createVideo = () => {
  const videoElement = videoElementRef.value;
  if (url.value.includes(".m3u8")) {
    if (!Hls.isSupported()) {
      console.log("不支持的格式");
      return;
    }
    const hls = new Hls();
    hls.loadSource(url.value);
    hls.attachMedia(videoElement);
    player.value = hls;
  } else if (url.value.includes(".flv")) {
    if (!flvJs.isSupported()) {
      console.log("不支持的格式");
      return;
    }
    const flvPlayer = flvJs.createPlayer({
      type: "flv",
      url: url.value,
    });
    flvPlayer.attachMediaElement(videoElement);
    flvPlayer.load();
    player.value = flvPlayer;
  } else {
    console.log("不支持的格式");
    return;
  }
};

const playVideo = () => {
  player.value?.play();
};

const suspendVideo = () => {
  player.value?.pause();
};

const destroyVideo = () => {
  if (player.value) {
    player.value?.pause();
    player.value?.unload();
    player.value?.detachMediaElement();
    player.value = null;
  }
};

defineExpose({ createVideo, destroyVideo, playVideo, suspendVideo });
</script>

<template>
  <div class="video-player">
    <video
      ref="videoElementRef"
      preload="auto"
      controls
      :style="{ width: width, height: height }"
      muted="false"
      :poster="poster"
    ></video>
  </div>
</template>

<style lang="css" scoped>
.video-player {
}
</style>

使用

<script setup>
  import videoFlv from '@/components/video-flv/video-flv.vue'
  const videoFlvRef = ref()
  const videoFlvIndex = ref(0)
  // 测试地址
  const list = reactive([
    {url:'https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv'}
  ])
const changeVideoFlv = (index) => {
  videoFlvIndex.value = index;
  if (index == 0) {
    videoFlvRef.value[list.value.length - 1].destroyVideo();
    videoFlvRef.value[index + 1].destroyVideo();
    videoFlvRef.value[index]?.createVideo();
    nextTick(() => {
      videoFlvRef.value[index]?.playVideo();
    });
  } else if (index == list.value.length - 1) {
    videoFlvRef.value[0].destroyVideo();
    videoFlvRef.value[index - 1].destroyVideo();
    videoFlvRef.value[index]?.createVideo();
    nextTick(() => {
      videoFlvRef.value[index]?.playVideo();
    });
  } else {
    videoFlvRef.value[index - 1].destroyVideo();
    videoFlvRef.value[index + 1].destroyVideo();
    videoFlvRef.value[index]?.createVideo();
    nextTick(() => {
      videoFlvRef.value[videoFlvIndex.value]?.playVideo();
    });
  }
};
onMounted(() => {
  changeVideoFlv(0);
});
onBeforeUnmount(() => {
  // 销毁 直播流
  for (let index = 0; index < list.value.length; index++) {
    videoFlvRef.value[index].destroyVideo();
  }
});
</script>

<template>
  <el-carousel
    :autoplay="false"
    indicator-position="none"
    type="card"
    width="100%"
    height="550px"
    @change="changeVideoFlv"
  >
    <el-carousel-item v-for="(item, index) in list" :key="index" >
      <dv-border-box10
        :color="['#4ccee3', '#4ccee3']"
        style="padding: 10px; box-sizing: border-box"
      >
        <video-flv
          ref="videoFlvRef"
          width="100%"
          height="550px"
          :url="item.url"
        />
      </dv-border-box10>
    </el-carousel-item>
  </el-carousel>
</template>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Write λ Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值