commit 8a0e1faf75ff491dedd77c7f2cb9521b3a4df9d7 Author: Tomas Date: Thu Oct 2 13:07:50 2025 +0200 Initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..af92807 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# Top-most EditorConfig file +root = true + +# Use same style for all files +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8241b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# Media files +/anime + +# Remuxed files +/video diff --git a/api/info.php b/api/info.php new file mode 100644 index 0000000..268ae5f --- /dev/null +++ b/api/info.php @@ -0,0 +1,36 @@ + array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "w"), +]; +$proc = proc_open(["ffprobe", "-show_streams", "-of", "json", $path], $descSpec, $pipes); + +fclose($pipes[0]); + +$stdout = stream_get_contents($pipes[1]); +$stderr = stream_get_contents($pipes[2]); +fclose($pipes[1]); +fclose($pipes[2]); + +$code = proc_close($proc); + +if ($code) +{ + header("Content-Type: text/plain"); + echo $stderr; +} else { + header("Content-Type: application/json"); + echo $stdout; +} +?> diff --git a/api/subtitles.php b/api/subtitles.php new file mode 100644 index 0000000..2d480d8 --- /dev/null +++ b/api/subtitles.php @@ -0,0 +1,35 @@ + 3600) + unlink("video/$file"); +} +?> diff --git a/api/video.php b/api/video.php new file mode 100644 index 0000000..8f81b17 --- /dev/null +++ b/api/video.php @@ -0,0 +1,36 @@ + 3600) + unlink("video/$file"); +} +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..90e3988 --- /dev/null +++ b/index.php @@ -0,0 +1,34 @@ +isFile()) + { + $files[] = $entry; + } +} + +?> + + + + Anime + + + + + diff --git a/js/player.js b/js/player.js new file mode 100644 index 0000000..e3abaab --- /dev/null +++ b/js/player.js @@ -0,0 +1,70 @@ +$(async function() +{ + const hash = location.hash.slice(1); + + $("#status").text("Fetching media info..."); + let res = await fetch(`api/info.php?file=${hash}`); + + $("#status").text("Parsing response data..."); + let media = await res.json(); + + $("#status").text("Constructing media player..."); + const audio = []; + const text = []; + + for (const stream of media.streams) switch (stream.codec_type) + { + case "audio": + audio.push({ + label: stream.tags.title, + language: stream.tags.language, + }); + break; + case "subtitle": + text.push({ + label: stream.tags.title, + language: stream.tags.language, + }); + break; + default: + break; + } + + $("#vid").append($("", {type: "video/mp4", src: `api/video.php?file=${hash}`})); + for (let i = 0; i < text.length; i++) + $("#vid").append($("", { + kind: "captions", + label: text[i].label, + srclang: text[i].language, + src: `api/subtitles.php?file=${hash}&s=${i}`, + })); + + $("#status").text("Building video.js player..."); + const player = videojs("vid"); + let audioTrackList = player.audioTracks(); + + for (let i = 0; i < audio.length; i++) + audioTrackList.addTrack(new videojs.AudioTrack({ + kind: "translation", + label: audio[i].label, + language: audio[i].language, + })); + + audioTrackList.addEventListener('change', function() { + for (var i = 0; i < audioTrackList.length; i++) { + var track = audioTrackList[i]; + + if (track.enabled) { + let time = player.currentTime() + player.src({type: "video/mp4", src: `api/video.php?file=${hash}&a=${i}`}) + player.ready(function(){ + player.currentTime(time); + player.play(); + }); + return; + } + } + }); + + $("#status").remove(); +}); diff --git a/player.html b/player.html new file mode 100644 index 0000000..17872cb --- /dev/null +++ b/player.html @@ -0,0 +1,14 @@ + + + + + + + + Anime - Player + + +

"Video Player"

+