mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-25 07:45:22 +00:00
Add hls/p2p video player
This commit is contained in:
parent
5c358010b0
commit
e3f8cfb49e
1 changed files with 198 additions and 0 deletions
198
resources/assets/components/presenter/VideoPlayer.vue
Normal file
198
resources/assets/components/presenter/VideoPlayer.vue
Normal file
|
@ -0,0 +1,198 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="status.sensitive == true" class="content-label-wrapper">
|
||||
<div class="text-light content-label">
|
||||
<p class="text-center">
|
||||
<i class="far fa-eye-slash fa-2x"></i>
|
||||
</p>
|
||||
<p class="h4 font-weight-bold text-center">
|
||||
Sensitive Content
|
||||
</p>
|
||||
<p class="text-center py-2 content-label-text">
|
||||
{{ status.spoiler_text ? status.spoiler_text : 'This post may contain sensitive content.'}}
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
<button @click="status.sensitive = false" class="btn btn-outline-light btn-block btn-sm font-weight-bold">See Post</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<div v-if="!shouldPlay" class="content-label-wrapper" :style="{ background: `linear-gradient(rgba(0, 0, 0, 0.2),rgba(0, 0, 0, 0.8)),url(${getPoster(status)})`, backgroundSize: 'cover'}">
|
||||
<div class="text-light content-label">
|
||||
<p class="mb-0">
|
||||
<button @click.prevent="handleShouldPlay" class="btn btn-link btn-block btn-sm font-weight-bold">
|
||||
<i class="fas fa-play fa-5x text-white"></i>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<video v-if="hasHls" ref="video" :class="{ fixedHeight: fixedHeight }" style="margin:0" playsinline controls autoplay="false" :poster="getPoster(status)">
|
||||
</video>
|
||||
|
||||
<video v-else class="card-img-top shadow" :class="{ fixedHeight: fixedHeight }" style="border-radius:15px;object-fit: contain;background-color: #000;" autoplay="false" controls :poster="getPoster(status)">
|
||||
<source :src="status.media_attachments[0].url" :type="status.media_attachments[0].mime">
|
||||
</video>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
import Hls from 'hls.js';
|
||||
import "plyr/dist/plyr.css";
|
||||
import Plyr from 'plyr';
|
||||
import { p2pml } from '@peertube/p2p-media-loader-core'
|
||||
import { Engine, initHlsJsPlayer } from '@peertube/p2p-media-loader-hlsjs'
|
||||
|
||||
export default {
|
||||
props: ['status', 'fixedHeight'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
shouldPlay: false,
|
||||
hasHls: undefined,
|
||||
hlsConfig: window.App.config.features.hls,
|
||||
liveSyncDurationCount: 7,
|
||||
isHlsSupported: false,
|
||||
isP2PSupported: false,
|
||||
engine: undefined,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.init();
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleShouldPlay(){
|
||||
this.shouldPlay = true;
|
||||
this.isHlsSupported = this.hlsConfig.enabled && Hls.isSupported();
|
||||
this.isP2PSupported = this.hlsConfig.enabled && this.hlsConfig.p2p && Engine.isSupported();
|
||||
this.$nextTick(() => {
|
||||
this.init();
|
||||
})
|
||||
},
|
||||
|
||||
init() {
|
||||
if(!this.status.sensitive && this.status.media_attachments[0]?.hls_manifest && this.isHlsSupported) {
|
||||
this.hasHls = true;
|
||||
this.$nextTick(() => {
|
||||
this.initHls();
|
||||
})
|
||||
} else {
|
||||
this.hasHls = false;
|
||||
}
|
||||
},
|
||||
|
||||
initHls() {
|
||||
let loader;
|
||||
if(this.isP2PSupported) {
|
||||
const config = {
|
||||
loader: {
|
||||
trackerAnnounce: [this.hlsConfig.tracker],
|
||||
rtcConfig: {
|
||||
iceServers: [
|
||||
{
|
||||
urls: [this.hlsConfig.ice]
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
};
|
||||
var engine = new Engine(config);
|
||||
if(this.hlsConfig.p2p_debug) {
|
||||
engine.on("peer_connect", peer => console.log("peer_connect", peer.id, peer.remoteAddress));
|
||||
engine.on("peer_close", peerId => console.log("peer_close", peerId));
|
||||
engine.on("segment_loaded", (segment, peerId) => console.log("segment_loaded from", peerId ? `peer ${peerId}` : "HTTP", segment.url));
|
||||
}
|
||||
loader = engine.createLoaderClass();
|
||||
} else {
|
||||
loader = Hls.DefaultConfig.loader;
|
||||
}
|
||||
const video = this.$refs.video;
|
||||
const source = this.status.media_attachments[0].hls_manifest;
|
||||
const player = new Plyr(video, {
|
||||
captions: {
|
||||
active: true,
|
||||
update: true,
|
||||
},
|
||||
});
|
||||
|
||||
const hls = new Hls({
|
||||
liveSyncDurationCount: this.liveSyncDurationCount,
|
||||
loader: loader,
|
||||
});
|
||||
let self = this;
|
||||
initHlsJsPlayer(hls);
|
||||
hls.loadSource(source);
|
||||
hls.attachMedia(video);
|
||||
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, function(event, data) {
|
||||
if(this.hlsConfig.debug) {
|
||||
console.log(event);
|
||||
console.log(data);
|
||||
}
|
||||
const defaultOptions = {};
|
||||
|
||||
const availableQualities = hls.levels.map((l) => l.height)
|
||||
if(this.hlsConfig.debug) {
|
||||
console.log(availableQualities);
|
||||
}
|
||||
availableQualities.unshift(0);
|
||||
|
||||
defaultOptions.quality = {
|
||||
default: 0,
|
||||
options: availableQualities,
|
||||
forced: true,
|
||||
onChange: (e) => self.updateQuality(e),
|
||||
}
|
||||
defaultOptions.i18n = {
|
||||
qualityLabel: {
|
||||
0: 'Auto',
|
||||
},
|
||||
}
|
||||
|
||||
hls.on(Hls.Events.LEVEL_SWITCHED, function(event, data) {
|
||||
var span = document.querySelector(".plyr__menu__container [data-plyr='quality'][value='0'] span")
|
||||
if (hls.autoLevelEnabled) {
|
||||
span.innerHTML = `Auto (${hls.levels[data.level].height}p)`
|
||||
} else {
|
||||
span.innerHTML = `Auto`
|
||||
}
|
||||
})
|
||||
|
||||
var player = new Plyr(video, defaultOptions);
|
||||
});
|
||||
},
|
||||
|
||||
updateQuality(newQuality) {
|
||||
if (newQuality === 0) {
|
||||
window.hls.currentLevel = -1;
|
||||
} else {
|
||||
window.hls.levels.forEach((level, levelIndex) => {
|
||||
if (level.height === newQuality) {
|
||||
if(this.hlsConfig.debug) {
|
||||
console.log("Found quality match with " + newQuality);
|
||||
}
|
||||
window.hls.currentLevel = levelIndex;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getPoster(status) {
|
||||
let url = status.media_attachments[0].preview_url;
|
||||
if(url.endsWith('no-preview.jpg') || url.endsWith('no-preview.png')) {
|
||||
return;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Reference in a new issue