Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fixing the inability to play MKV video files online and enhancin… #3181

Merged
merged 1 commit into from
May 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
144 changes: 105 additions & 39 deletions frontend/src/components/files/VideoPlayer.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
<template>
<video ref="videoPlayer" class="video-max video-js" controls>
<source :src="source" />
<track
kind="subtitles"
v-for="(sub, index) in subtitles"
:key="index"
:src="sub"
:label="subLabel(sub)"
:default="index === 0"
/>
<video ref="videoPlayer" class="video-max video-js" controls preload="auto">
<source />
<track kind="subtitles" v-for="(sub, index) in subtitles" :key="index" :src="sub" :label="subLabel(sub)"

Check warning on line 4 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Replace `·kind="subtitles"·v-for="(sub,·index)·in·subtitles"·:key="index"·:src="sub"` with `⏎······kind="subtitles"⏎······v-for="(sub,·index)·in·subtitles"⏎······:key="index"⏎······:src="sub"⏎·····`

Check warning on line 4 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Replace `·kind="subtitles"·v-for="(sub,·index)·in·subtitles"·:key="index"·:src="sub"` with `⏎······kind="subtitles"⏎······v-for="(sub,·index)·in·subtitles"⏎······:key="index"⏎······:src="sub"⏎·····`
:default="index === 0" />

Check warning on line 5 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `⏎···`

Check warning on line 5 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `⏎···`
<p class="vjs-no-js">
Sorry, your browser doesn't support embedded videos, but don't worry, you
can <a :href="source">download it</a>
Expand All @@ -18,18 +12,18 @@
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";
import { ref, onMounted, onBeforeUnmount, nextTick, } from "vue";

Check warning on line 15 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Delete `,`

Check warning on line 15 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Delete `,`
import videojs from "video.js";
import type Player from "video.js/dist/types/player";
import "videojs-mobile-ui";
import "videojs-hotkeys";

import "video.js/dist/video-js.min.css";
import "videojs-mobile-ui/dist/videojs-mobile-ui.css";

const videoPlayer = ref<HTMLElement | null>(null);
const player = ref<Player | null>(null);


Check warning on line 26 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Delete `⏎`

Check warning on line 26 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Delete `⏎`
const props = withDefaults(
defineProps<{
source: string;
Expand All @@ -41,33 +35,14 @@
}
);

onMounted(() => {
player.value = videojs(
videoPlayer.value!,
{
html5: {
// needed for customizable subtitles
// TODO: add to user settings
nativeTextTracks: false,
},
plugins: {
hotkeys: {
volumeStep: 0.1,
seekStep: 10,
enableModifiersForNumbers: false,
},
},
...props.options,
},
// onReady callback
async () => {
// player.value!.log("onPlayerReady", this);
}
);
// TODO: need to test on mobile
// @ts-ignore
player.value!.mobileUi();
});
const source = ref(props.source)

Check warning on line 38 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `;`

Check warning on line 38 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `;`
const sourceType = ref("")

Check warning on line 39 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `;`

Check warning on line 39 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `;`

nextTick(() => {
initVideoPlayer()

Check warning on line 42 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `;`

Check warning on line 42 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `;`
})

Check warning on line 43 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `;`

Check warning on line 43 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Insert `;`

onMounted(() => { });

Check warning on line 45 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Delete `·`

Check warning on line 45 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Delete `·`

onBeforeUnmount(() => {
if (player.value) {
Expand All @@ -76,6 +51,67 @@
}
});

const initVideoPlayer = async () => {
try {
const lang = document.documentElement.lang;
const languagePack = await (languageImports[lang] || languageImports.en)?.();

Check warning on line 57 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Replace `languageImports[lang]·||·languageImports.en` with `⏎······languageImports[lang]·||·languageImports.en⏎····`

Check warning on line 57 in frontend/src/components/files/VideoPlayer.vue

View workflow job for this annotation

GitHub Actions / lint-frontend

Replace `languageImports[lang]·||·languageImports.en` with `⏎······languageImports[lang]·||·languageImports.en⏎····`
videojs.addLanguage('videoPlayerLocal', languagePack.default);
sourceType.value = ""

//
sourceType.value = getSourceType(source.value);

const srcOpt = { sources: { src: props.source, type: sourceType.value } }
//Supporting localized language display.
const langOpt = { language: "videoPlayerLocal" }
// support for playback at different speeds.
const playbackRatesOpt = { playbackRates: [0.5, 1, 1.5, 2, 2.5, 3] }
let options = getOptions(props.options, langOpt, srcOpt, playbackRatesOpt)
player.value = videojs(videoPlayer.value!, options, () => {
});

// TODO: need to test on mobile
// @ts-ignore
player.value!.mobileUi();
} catch (error) {
console.error("Error initializing video player:", error);
}

}

const getOptions = (...srcOpt: any[]) => {
const options = {
controlBar: {
skipButtons: {
forward: 5,
backward: 5
}

},
html5: {
nativeTextTracks: false,
},
plugins: {
hotkeys: {
volumeStep: 0.1,
seekStep: 10,
enableModifiersForNumbers: false,
},
},
};

return videojs.obj.merge(options, ...srcOpt);
}

// Attempting to fix the issue of being unable to play .MKV format video files
const getSourceType = (source: string) => {
const fileExtension = source ? source.split("?")[0].split(".").pop() : "";
if (fileExtension?.toLowerCase() === "mkv") {
return "video/mp4";
}
return "";
};

const subLabel = (subUrl: string) => {
let url: URL;
try {
Expand All @@ -95,6 +131,36 @@

return label;
};

interface LanguageImports {
[key: string]: () => Promise<any>;
}

const languageImports: LanguageImports = {
'he': () => import('video.js/dist/lang/he.json'),
'hu': () => import('video.js/dist/lang/hu.json'),
'ar': () => import('video.js/dist/lang/ar.json'),
'de': () => import('video.js/dist/lang/de.json'),
'el': () => import('video.js/dist/lang/el.json'),
'en': () => import('video.js/dist/lang/en.json'),
'es': () => import('video.js/dist/lang/es.json'),
'fr': () => import('video.js/dist/lang/fr.json'),
'it': () => import('video.js/dist/lang/it.json'),
'ja': () => import('video.js/dist/lang/ja.json'),
'ko': () => import('video.js/dist/lang/ko.json'),
'nl-be': () => import('video.js/dist/lang/nl.json'),
'pl': () => import('video.js/dist/lang/pl.json'),
'pt-br': () => import('video.js/dist/lang/pt-BR.json'),
'pt': () => import('video.js/dist/lang/pt-PT.json'),
'ro': () => import('video.js/dist/lang/ro.json'),
'ru': () => import('video.js/dist/lang/ru.json'),
'sk': () => import('video.js/dist/lang/sk.json'),
'tr': () => import('video.js/dist/lang/tr.json'),
'uk': () => import('video.js/dist/lang/uk.json'),
'zh-cn': () => import('video.js/dist/lang/zh-CN.json'),
'zh-tw': () => import('video.js/dist/lang/zh-TW.json'),
};

</script>
<style scoped>
.video-max {
Expand Down