Initial commit
This commit is contained in:
10
.editorconfig
Normal file
10
.editorconfig
Normal file
@ -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
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Media files
|
||||||
|
/anime
|
||||||
|
|
||||||
|
# Remuxed files
|
||||||
|
/video
|
||||||
36
api/info.php
Normal file
36
api/info.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
chdir("..");
|
||||||
|
require_once "src/util.php";
|
||||||
|
|
||||||
|
$query = $_SERVER["QUERY_STRING"];
|
||||||
|
parse_str($query, $param);
|
||||||
|
|
||||||
|
$path = urlsafe_b64decode($param["file"]);
|
||||||
|
$path = "./" . $path;
|
||||||
|
$path = str_replace("..", "", $path);
|
||||||
|
|
||||||
|
$descSpec = [
|
||||||
|
0 => 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;
|
||||||
|
}
|
||||||
|
?>
|
||||||
35
api/subtitles.php
Normal file
35
api/subtitles.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
chdir("..");
|
||||||
|
require_once "src/util.php";
|
||||||
|
require_once "src/ffmpeg.php";
|
||||||
|
|
||||||
|
$query = $_SERVER["QUERY_STRING"];
|
||||||
|
parse_str($query, $param);
|
||||||
|
|
||||||
|
$path = urlsafe_b64decode($param["file"]);
|
||||||
|
$path = "./" . $path;
|
||||||
|
$path = str_replace("..", "", $path);
|
||||||
|
|
||||||
|
$index = $param["s"] ?? 0;
|
||||||
|
|
||||||
|
if (!is_dir("video/"))
|
||||||
|
mkdir("video/");
|
||||||
|
|
||||||
|
$err = ffmpeg($path, "video/$query.vtt", ["-map", "0:s:$index"]);
|
||||||
|
|
||||||
|
if ($err)
|
||||||
|
{
|
||||||
|
header("Content-Type: text/plain");
|
||||||
|
echo $err;
|
||||||
|
} else {
|
||||||
|
header("Location: ../video/$query.vtt", true, 302);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove old videos and subtitles
|
||||||
|
foreach (scandir("video/") as $file)
|
||||||
|
{
|
||||||
|
$atime = fileatime("video/$file");
|
||||||
|
if (time() - $atime > 3600)
|
||||||
|
unlink("video/$file");
|
||||||
|
}
|
||||||
|
?>
|
||||||
36
api/video.php
Normal file
36
api/video.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
chdir("..");
|
||||||
|
require_once "src/util.php";
|
||||||
|
require_once "src/ffmpeg.php";
|
||||||
|
|
||||||
|
$query = $_SERVER["QUERY_STRING"];
|
||||||
|
parse_str($query, $param);
|
||||||
|
|
||||||
|
$path = urlsafe_b64decode($param["file"]);
|
||||||
|
$path = "./" . $path;
|
||||||
|
$path = str_replace("..", "", $path);
|
||||||
|
|
||||||
|
$video = $param["v"] ?? 0;
|
||||||
|
$audio = $param["a"] ?? 0;
|
||||||
|
|
||||||
|
if (!is_dir("video/"))
|
||||||
|
mkdir("video/");
|
||||||
|
|
||||||
|
$err = ffmpeg($path, "video/$query.mp4", ["-map", "0:v:$video", "-map", "0:a:$audio", "-c", "copy"]);
|
||||||
|
|
||||||
|
if ($err)
|
||||||
|
{
|
||||||
|
header("Content-Type: text/plain");
|
||||||
|
echo $err;
|
||||||
|
} else {
|
||||||
|
header("Location: ../video/$query.mp4", true, 302);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove old videos and subtitles
|
||||||
|
foreach (scandir("video/") as $file)
|
||||||
|
{
|
||||||
|
$atime = fileatime("video/$file");
|
||||||
|
if (time() - $atime > 3600)
|
||||||
|
unlink("video/$file");
|
||||||
|
}
|
||||||
|
?>
|
||||||
34
index.php
Normal file
34
index.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
require_once "src/util.php";
|
||||||
|
|
||||||
|
$files = [];
|
||||||
|
$dirIter = new RecursiveDirectoryIterator("anime");
|
||||||
|
$iter = new RecursiveIteratorIterator($dirIter);
|
||||||
|
|
||||||
|
foreach ($iter as $entry)
|
||||||
|
{
|
||||||
|
if ($entry->isFile())
|
||||||
|
{
|
||||||
|
$files[] = $entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Anime</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ul>
|
||||||
|
<?php
|
||||||
|
foreach ($files as $file)
|
||||||
|
{
|
||||||
|
$path = $file->getPathName();
|
||||||
|
$id = urlsafe_b64encode($path);
|
||||||
|
echo "<li><a href=\"player.html#$id\">$path</a></li>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
70
js/player.js
Normal file
70
js/player.js
Normal file
@ -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($("<source>", {type: "video/mp4", src: `api/video.php?file=${hash}`}));
|
||||||
|
for (let i = 0; i < text.length; i++)
|
||||||
|
$("#vid").append($("<track>", {
|
||||||
|
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();
|
||||||
|
});
|
||||||
14
player.html
Normal file
14
player.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link href="https://lesbian.ddns.net/Tomas/-/files/lib/web/video-js.css" rel="stylesheet" />
|
||||||
|
<script src="https://lesbian.ddns.net/Tomas/-/files/lib/web/video.min.js"></script>
|
||||||
|
<script src="https://lesbian.ddns.net/Tomas/-/files/lib/web/jquery.min.js"></script>
|
||||||
|
<script src="js/player.js"></script>
|
||||||
|
<title>Anime - Player</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2 id="status">"Video Player"</h2>
|
||||||
|
<video id="vid" class="video-js" controls width="480" height="360"/>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
44
src/ffmpeg.php
Normal file
44
src/ffmpeg.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
require_once "src/util.php";
|
||||||
|
|
||||||
|
|
||||||
|
function ffmpeg($input, $output, $params)
|
||||||
|
{
|
||||||
|
if (!is_file($input))
|
||||||
|
return "Could not open $input";
|
||||||
|
|
||||||
|
if (is_file($output))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$descSpec = [
|
||||||
|
0 => array("pipe", "r"),
|
||||||
|
1 => array("pipe", "w"),
|
||||||
|
2 => array("pipe", "w"),
|
||||||
|
];
|
||||||
|
$proc = proc_open(array_merge(["ffmpeg", "-i", $input], $params, [$output]), $descSpec, $pipes);
|
||||||
|
|
||||||
|
if (is_resource($proc))
|
||||||
|
{
|
||||||
|
fclose($pipes[0]);
|
||||||
|
|
||||||
|
$stderr = stream_get_contents($pipes[2]);
|
||||||
|
|
||||||
|
fclose($pipes[1]);
|
||||||
|
fclose($pipes[2]);
|
||||||
|
$failed = proc_close($proc);
|
||||||
|
|
||||||
|
if ($failed)
|
||||||
|
{
|
||||||
|
if (is_file($output))
|
||||||
|
unlink($output);
|
||||||
|
return $stderr;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "Failed to initialize ffmpeg";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
39
src/util.php
Normal file
39
src/util.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
function urlsafe_b64encode($string)
|
||||||
|
{
|
||||||
|
$data = base64_encode($string);
|
||||||
|
$data = str_replace(array('+','/','='),array('-','_',''),$data);
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function urlsafe_b64decode($string)
|
||||||
|
{
|
||||||
|
$data = str_replace(array('-','_'),array('+','/'),$string);
|
||||||
|
$mod4 = strlen($data) % 4;
|
||||||
|
if ($mod4) {
|
||||||
|
$data .= substr('====', $mod4);
|
||||||
|
}
|
||||||
|
return base64_decode($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendfile($path)
|
||||||
|
{
|
||||||
|
$file = fopen($path, "rb");
|
||||||
|
|
||||||
|
header("Content-Length: " . filesize($path));
|
||||||
|
|
||||||
|
ob_end_flush();
|
||||||
|
flush();
|
||||||
|
|
||||||
|
while (!feof($file))
|
||||||
|
{
|
||||||
|
$chunk = fread($file, 1024);
|
||||||
|
echo $chunk;
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user