<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>m3u8, flv, mp4格式视频demo源码分享</title>
<link rel="stylesheet" type="text/css" href="http://qqxqs.com/resource/wetpl/default/web/css/index_new.css"/>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script src="http://bilibili.github.io/flv.js/dist/flv.js"></script>
<style>
* { margin: 0; padding: 0 }
::-webkit-scrollbar { width: 0 !important; display: none }
select { width: 200px; height: 30px; text-indent: 6px; }
html, body { width: 100vw; height: 100vh; position: fixed; }
div#app { width: 100vw; height: 100vh; position: fixed; overflow-y: auto; }
article.fruit { display: flex; align-items: center; padding: 15px 10px 5px; }
article.videoBox { display: flex; flex-wrap: wrap; padding: 5px; }
section { flex: 1; border: 1px solid #006699; margin: 5px; }
section>h4 { padding: 5px 10px; background: #00669994; color: #fff; font-size: 16px; font-weight: 400; text-align: center; }
section>aside { width: 940px; height: 416px; display: flex; justify-content: space-evenly; align-items: center; flex-wrap: wrap; padding: 10px 0; }
section>aside>video { object-fit: fill; margin: 4px 0; background-color: #cccccc; outline: 1px solid #cccccc; }
section>aside .video-js { margin: 4px 0; }
</style>
</head>
<body>
<div id="app">
<article class="fruit">
分屏:
<select v-model="tab">
<option :value="1">一分屏</option>
<option :value="4">四分屏</option>
<option :value="6">六分屏</option>
</select>
</article>
<article class="videoBox">
<section class="m3u8">
<h4>m3u8</h4>
<aside>
<video v-for="(v,k) in splitVideom3u8" :key="k" :ref=`hls_video_player${v.id}` autoplay controls preload muted :width="tab == 6 ? 300 : tab == 4 ? 460 : 920" :height="tab == 6 ? 200 : tab == 4 ? 200 : 410" />
</aside>
</section>
<section class="flv">
<h4>flv</h4>
<aside>
<video v-for="(v, k) in splitVideoFlv" :key="k" :id=`flv_video_player${v.id}` controls preload muted :width="tab == 6 ? 300 : tab == 4 ? 460 : 920" :height="tab == 6 ? 200 : tab == 4 ? 200 : 410" />
</aside>
</section>
<section class="MP4">
<h4>mp4</h4>
<aside>
<video v-for="(v, k) in videoFlv" :key="k" autoplay loop muted :src="videoMp4" v-show="v.id<=tab" :width="tab == 6 ? 300 : tab == 4 ? 460 : 920" :height="tab == 6 ? 200 : tab == 4 ? 200 : 410" />
</aside>
</section>
</article>
</div>
<script>
const app = {
data() {
return {
videom3u8: [
{ id: 1, url: 'http://ivi.bupt.edu.cn/hls/cctv9hd.m3u8' },
{ id: 2, url: 'http://ivi.bupt.edu.cn/hls/hunanhd.m3u8' },
{ id: 3, url: 'http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8' },
{ id: 4, url: 'http://ivi.bupt.edu.cn/hls/cctv2hd.m3u8' },
{ id: 5, url: 'http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8' },
{ id: 6, url: 'http://ivi.bupt.edu.cn/hls/cctv4hd.m3u8' },
// { id: 7, url: 'http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8' },
// { id: 8, url: 'http://ivi.bupt.edu.cn/hls/cctv8hd.m3u8' },
// { id: 9, url: 'http://192.168.31.186:8080/live/qiangji/qiangji.m3u8' },
],
videoFlv: [
{ id: 1, url: 'http://1011.hlsplay.aodianyun.com/demo/game.flv' },
{ id: 2, url: 'http://1011.hlsplay.aodianyun.com/demo/game.flv' },
{ id: 3, url: 'http://1011.hlsplay.aodianyun.com/demo/game.flv' },
{ id: 4, url: 'http://1011.hlsplay.aodianyun.com/demo/game.flv' },
{ id: 5, url: 'http://1011.hlsplay.aodianyun.com/demo/game.flv' },
{ id: 6, url: 'http://1011.hlsplay.aodianyun.com/demo/game.flv' }
// { id: 7, url: 'http://192.168.31.186:8080/live/34020000001320000002@34020000001320000002.flv' }
// { id: 8, url: 'http://192.168.31.186:8080/live/34020000001320000002@34020000001320000002.flv' }
// { id: 9, url: 'http://192.168.31.186:8080/live/34020000001320000002@34020000001320000002.flv' }
],
videoMp4: 'https://video_shejigao.redocn.com/video/201801/20180131/Redcon_201801291122194680611553.mp4',
splitVideom3u8: [],
splitVideoFlv: [],
flvPlayer: [],
hlsPlayer: [],
tab: 6
}
},
created() {
this.splitVideom3u8 = this.videom3u8.slice(0, this.tab);
this.splitVideoFlv = this.videoFlv.slice(0, this.tab);
},
mounted() {
this.$nextTick(() => {
this.flv_createVideo(this.videoFlv);
this.hls_createVideo(this.videom3u8);
});
},
methods: {
/* Flv 加载 .flv 格式视频 */
// 分屏切换调起
flv_splitScreen(use, used) {
console.log(use, used);
if (this.flvPlayer.length > 0) {
if (used === use) {
return false;
} else if (used > use) {
this.splitVideoFlv.splice(use);
this.flvPlayer.splice(use).forEach((v, k) => {
this.flv_destroy(this.flvPlayer[use + k]);
})
} else if (used < use) {
let newSlice = this.videoFlv.slice(used, use);
this.splitVideoFlv = [...this.splitVideoFlv, ...newSlice]
setTimeout(() => {
newSlice.forEach((v, k) => {
this.flv_created(v, (k + used));
})
}, 300)
}
}
},
// 初始化加载 Flv全部视频
flv_createVideo(event) {
if (flvjs.isSupported()) {
event.forEach((v, k) => {
this.flv_created(v, k)
})
}
},
// 创建每个 Flv视频对象
flv_created(v, k) {
console.log(this.flvPlayer)
this.flvPlayer[k] = flvjs.createPlayer({
type: 'flv',
isLive: true,
hasAudio: false,
stashInitialSize: 128,
isAutoPlay: false,
isContinue: false,
lazyLoad: false,
url: v.url
}, {
//当带音频播放时,config部分配置项尽量采取默认状态,否则过分优化会造成卡死
enableWorker: false,
enableStashBuffer: false
})
flvjs.LoggingControl.enableVerbose = false;
this.flvPlayer[k].attachMediaElement(document.getElementById(`flv_video_player${v.id}`))
this.flvPlayer[k].load()
setTimeout(() => {
document.getElementById(`flv_video_player${v.id}`).play();
this.flvPlayer[k].play()
}, 1000)
},
// 销毁 Flv对象、dom节点
flv_destroy(player) {
if (player) {
player.pause();
player.unload();
player.detachMediaElement();
player.destroy();
player = null;
}
},
/* ******************************************************************************************************************* */
/* Hls 加载 .m3u8 格式视频 */
// 分屏切换调起
hls_splitScreen(use, used) {
console.log(use, used);
if (this.hlsPlayer.length > 0) {
if (used === use) {
return false;
} else if (used > use) {
this.splitVideom3u8.splice(use);
this.hlsPlayer.splice(use).forEach((v, k) => {
this.hls_destroy(this.hlsPlayer[use + k]);
})
} else if (used < use) {
let newSlice = this.videom3u8.slice(used, use);
this.splitVideom3u8 = [...this.splitVideom3u8, ...newSlice]
setTimeout(() => {
newSlice.forEach((v, k) => {
this.hls_created(v, (k + used));
})
}, 300)
}
}
},
// 初始化加载 Hls全部视频
hls_createVideo(event) {
if (Hls.isSupported()) {
event.forEach((v, k) => {
this.hls_created(v, k)
})
}
},
// 创建每个 Hls视频对象
hls_created(v, k) {
console.log(this.hlsPlayer)
if (Hls.isSupported()) {
this.hlsPlayer[k] = new Hls();
this.hlsPlayer[k].loadSource(v.url);
this.hlsPlayer[k].attachMedia(this.$refs[`hls_video_player${v.id}`]);
setTimeout(() => {
this.hlsPlayer[k].on(Hls.Events.MANIFEST_PARSED, async () => {
await this.$refs[`hls_video_player${v.id}`].play();
});
}, 10)
}
},
// 销毁 Hls对象、dom节点
hls_destroy(player) {
if (player) {
player.pause();
player.destroy();
player = null;
}
},
},
watch: {
'tab': function(use, used) {
this.flv_splitScreen(+use, used);
this.hls_splitScreen(+use, used);
}
}
}
Vue.createApp(app).mount('#app')
</script>
</body>
</html>