123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- <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>
|