Switch to go-vod
parent
8569af561b
commit
6b566b34e0
|
@ -58,7 +58,7 @@ return [
|
||||||
|
|
||||||
['name' => 'Archive#archive', 'url' => '/api/archive/{id}', 'verb' => 'PATCH'],
|
['name' => 'Archive#archive', 'url' => '/api/archive/{id}', 'verb' => 'PATCH'],
|
||||||
|
|
||||||
['name' => 'Video#transcode', 'url' => '/api/video/transcode/{fileid}/{profile}', 'verb' => 'GET'],
|
['name' => 'Video#transcode', 'url' => '/api/video/transcode/{client}/{fileid}/{profile}', 'verb' => 'GET'],
|
||||||
|
|
||||||
// Config API
|
// Config API
|
||||||
['name' => 'Other#setUserConfig', 'url' => '/api/config/{key}', 'verb' => 'PUT'],
|
['name' => 'Other#setUserConfig', 'url' => '/api/config/{key}', 'verb' => 'PUT'],
|
||||||
|
|
|
@ -82,34 +82,33 @@ class VideoSetup extends Command
|
||||||
return $this->suggestDisable($output);
|
return $this->suggestDisable($output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check go-transcode binary
|
// Check go-vod binary
|
||||||
$output->writeln('Checking for go-transcode binary');
|
$output->writeln('Checking for go-vod binary');
|
||||||
|
|
||||||
// Detect architecture
|
// Detect architecture
|
||||||
$arch = \OCA\Memories\Util::getArch();
|
$arch = \OCA\Memories\Util::getArch();
|
||||||
$libc = \OCA\Memories\Util::getLibc();
|
|
||||||
|
|
||||||
if (!$arch || !$libc) {
|
if (!$arch) {
|
||||||
$output->writeln('<error>Compatible go-transcode binary not found</error>');
|
$output->writeln('<error>Compatible go-vod binary not found</error>');
|
||||||
$this->suggestGoTranscode($output);
|
$this->suggestGoVod($output);
|
||||||
|
|
||||||
return $this->suggestDisable($output);
|
return $this->suggestDisable($output);
|
||||||
}
|
}
|
||||||
|
|
||||||
$goTranscodePath = realpath(__DIR__."/../../exiftool-bin/go-transcode-{$arch}-{$libc}");
|
$goVodPath = realpath(__DIR__."/../../exiftool-bin/go-vod-{$arch}");
|
||||||
$output->writeln("Trying go-transcode from {$goTranscodePath}");
|
$output->writeln("Trying go-vod from {$goVodPath}");
|
||||||
chmod($goTranscodePath, 0755);
|
chmod($goVodPath, 0755);
|
||||||
|
|
||||||
$goTranscode = shell_exec($goTranscodePath.' --help');
|
$goVod = shell_exec($goVodPath.' test');
|
||||||
if (!$goTranscode || false === strpos($goTranscode, 'Available Commands')) {
|
if (!$goVod || false === strpos($goVod, 'test successful')) {
|
||||||
$output->writeln('<error>go-transcode could not be run</error>');
|
$output->writeln('<error>go-vod could not be run</error>');
|
||||||
$this->suggestGoTranscode($output);
|
$this->suggestGoVod($output);
|
||||||
|
|
||||||
return $this->suggestDisable($output);
|
return $this->suggestDisable($output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go transcode is working. Yay!
|
// Go transcode is working. Yay!
|
||||||
$output->writeln('go-transcode is installed!');
|
$output->writeln('go-vod is installed!');
|
||||||
$output->writeln('');
|
$output->writeln('');
|
||||||
$output->writeln('You can use transcoding and HLS streaming');
|
$output->writeln('You can use transcoding and HLS streaming');
|
||||||
$output->writeln('This is recommended for better performance, but has implications if');
|
$output->writeln('This is recommended for better performance, but has implications if');
|
||||||
|
@ -127,10 +126,7 @@ class VideoSetup extends Command
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tConfig = realpath(__DIR__.'/../../transcoder.yaml');
|
$this->config->setSystemValue('memories.transcoder', $goVodPath);
|
||||||
|
|
||||||
$this->config->setSystemValue('memories.transcoder', $goTranscodePath);
|
|
||||||
$this->config->setSystemValue('memories.transcoder_config', $tConfig);
|
|
||||||
$this->config->setSystemValue('memories.no_transcode', false);
|
$this->config->setSystemValue('memories.no_transcode', false);
|
||||||
$output->writeln('Transcoding and HLS are now enabled!');
|
$output->writeln('Transcoding and HLS are now enabled!');
|
||||||
|
|
||||||
|
@ -153,10 +149,10 @@ class VideoSetup extends Command
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function suggestGoTranscode(OutputInterface $output): void
|
protected function suggestGoVod(OutputInterface $output): void
|
||||||
{
|
{
|
||||||
$output->writeln('You may build go-transcode from source');
|
$output->writeln('You may build go-vod from source');
|
||||||
$output->writeln('It can be downloaded from https://github.com/pulsejet/go-transcode');
|
$output->writeln('It can be downloaded from https://github.com/pulsejet/go-vod');
|
||||||
$output->writeln('Once built, point the path to the binary in the config for `memories.transcoder`');
|
$output->writeln('Once built, point the path to the binary in the config for `memories.transcoder`');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,9 @@ class VideoController extends ApiBase
|
||||||
*
|
*
|
||||||
* Transcode a video to HLS by proxy
|
* Transcode a video to HLS by proxy
|
||||||
*
|
*
|
||||||
* @param string fileid
|
|
||||||
* @param string video profile
|
|
||||||
*
|
|
||||||
* @return JSONResponse an empty JSONResponse with respective http status code
|
* @return JSONResponse an empty JSONResponse with respective http status code
|
||||||
*/
|
*/
|
||||||
public function transcode(string $fileid, string $profile): Http\Response
|
public function transcode(string $client, string $fileid, string $profile): Http\Response
|
||||||
{
|
{
|
||||||
$user = $this->userSession->getUser();
|
$user = $this->userSession->getUser();
|
||||||
if (null === $user) {
|
if (null === $user) {
|
||||||
|
@ -53,6 +50,11 @@ class VideoController extends ApiBase
|
||||||
return new JSONResponse(['message' => 'Transcoding disabled'], Http::STATUS_FORBIDDEN);
|
return new JSONResponse(['message' => 'Transcoding disabled'], Http::STATUS_FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check client identifier is 8 characters or more
|
||||||
|
if (\strlen($client) < 8) {
|
||||||
|
return new JSONResponse(['message' => 'Invalid client identifier'], Http::STATUS_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
// Get file
|
// Get file
|
||||||
$files = $this->rootFolder->getUserFolder($user->getUID())->getById($fileid);
|
$files = $this->rootFolder->getUserFolder($user->getUID())->getById($fileid);
|
||||||
if (0 === \count($files)) {
|
if (0 === \count($files)) {
|
||||||
|
@ -78,14 +80,13 @@ class VideoController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make upstream request
|
// Make upstream request
|
||||||
[$data, $contentType, $returnCode] = $this->getUpstream($path, $profile);
|
[$data, $contentType, $returnCode] = $this->getUpstream($client, $path, $profile);
|
||||||
|
|
||||||
// If status code was 0, it's likely the server is down
|
// If status code was 0, it's likely the server is down
|
||||||
// Make one attempt to start if we can't find the process
|
// Make one attempt to start if we can't find the process
|
||||||
if (0 === $returnCode) {
|
if (0 === $returnCode) {
|
||||||
$transcoder = $this->config->getSystemValue('memories.transcoder', false);
|
$transcoder = $this->config->getSystemValue('memories.transcoder', false);
|
||||||
$tConfig = $this->config->getSystemValue('memories.transcoder_config', false);
|
if (!$transcoder) {
|
||||||
if (!$transcoder || !$tConfig) {
|
|
||||||
return new JSONResponse(['message' => 'Transcoder not configured'], Http::STATUS_INTERNAL_SERVER_ERROR);
|
return new JSONResponse(['message' => 'Transcoder not configured'], Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,15 +98,12 @@ class VideoController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if already running
|
// Check if already running
|
||||||
exec('ps a | grep go-transcode | grep -v grep', $procs);
|
shell_exec("pkill {$transcoder}");
|
||||||
if (0 === \count($procs)) {
|
shell_exec("{$env} nohup {$transcoder} > {$tmpDir}/go-vod.log 2>&1 & > /dev/null");
|
||||||
shell_exec("mkdir -p {$tmpDir}/transcoder"); // php func has some weird problems
|
|
||||||
shell_exec("{$env} nohup {$transcoder} serve --config {$tConfig} > {$tmpDir}/transcoder/run.log 2>&1 & > /dev/null");
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for 2s and try again
|
// wait for 1s and try again
|
||||||
sleep(2);
|
sleep(1);
|
||||||
[$data, $contentType, $returnCode] = $this->getUpstream($path, $profile);
|
[$data, $contentType, $returnCode] = $this->getUpstream($client, $path, $profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check data was received
|
// Check data was received
|
||||||
|
@ -117,15 +115,15 @@ class VideoController extends ApiBase
|
||||||
$response = new DataDisplayResponse($data, Http::STATUS_OK, [
|
$response = new DataDisplayResponse($data, Http::STATUS_OK, [
|
||||||
'Content-Type' => $contentType,
|
'Content-Type' => $contentType,
|
||||||
]);
|
]);
|
||||||
$response->cacheFor(3600 * 24, false, false);
|
$response->cacheFor(0, false, false);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getUpstream($path, $profile)
|
private function getUpstream($client, $path, $profile)
|
||||||
{
|
{
|
||||||
$path = rawurlencode($path);
|
$path = rawurlencode($path);
|
||||||
$ch = curl_init("http://127.0.0.1:47788/vod/{$path}/{$profile}");
|
$ch = curl_init("http://127.0.0.1:47788/{$client}{$path}/{$profile}");
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||||
|
|
|
@ -17,11 +17,9 @@ mv "exiftool-$exifver" exiftool
|
||||||
rm -rf *.zip exiftool/t exiftool/html
|
rm -rf *.zip exiftool/t exiftool/html
|
||||||
chmod 755 exiftool/exiftool
|
chmod 755 exiftool/exiftool
|
||||||
|
|
||||||
gotranscode="v0.0.3"
|
govod="0.0.2"
|
||||||
wget -q "https://github.com/pulsejet/go-transcode/releases/download/$gotranscode/go-transcode-amd64-musl"
|
wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-amd64"
|
||||||
wget -q "https://github.com/pulsejet/go-transcode/releases/download/$gotranscode/go-transcode-amd64-glibc"
|
wget -q "https://github.com/pulsejet/go-vod/releases/download/$govod/go-vod-aarch64"
|
||||||
wget -q "https://github.com/pulsejet/go-transcode/releases/download/$gotranscode/go-transcode-aarch64-musl"
|
chmod 755 go-vod-*
|
||||||
wget -q "https://github.com/pulsejet/go-transcode/releases/download/$gotranscode/go-transcode-aarch64-glibc"
|
|
||||||
chmod 755 go-transcode-*
|
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|
|
@ -14,6 +14,10 @@ const config_noTranscode = loadState(
|
||||||
<string>"UNSET"
|
<string>"UNSET"
|
||||||
) as boolean | string;
|
) as boolean | string;
|
||||||
|
|
||||||
|
// Generate client id for this instance
|
||||||
|
// Does not need to be cryptographically secure
|
||||||
|
const clientId = Math.random().toString(36).substring(2, 15).padEnd(12, "0");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if slide has video content
|
* Check if slide has video content
|
||||||
*
|
*
|
||||||
|
@ -89,7 +93,7 @@ class VideoContentSetup {
|
||||||
// Create hls sources if enabled
|
// Create hls sources if enabled
|
||||||
let sources: any[] = [];
|
let sources: any[] = [];
|
||||||
const baseUrl = generateUrl(
|
const baseUrl = generateUrl(
|
||||||
`/apps/memories/api/video/transcode/${fileid}`
|
`/apps/memories/api/video/transcode/${clientId}/${fileid}`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!config_noTranscode) {
|
if (!config_noTranscode) {
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
# allow debug outputs
|
|
||||||
debug: false
|
|
||||||
|
|
||||||
# mount debug pprof endpoint at /debug/pprof/
|
|
||||||
pprof: false
|
|
||||||
|
|
||||||
# bind server to IP:PORT (use :47788 for all connections)
|
|
||||||
# DO NOT expose this port to the world
|
|
||||||
bind: localhost:47788
|
|
||||||
|
|
||||||
# X-Forwarded-For headers will be used to determine the client IP
|
|
||||||
proxy: true
|
|
||||||
|
|
||||||
# For static files
|
|
||||||
vod:
|
|
||||||
# Root directory for media
|
|
||||||
media-dir: /
|
|
||||||
|
|
||||||
# Temporary transcode output directory, if empty, default tmp folder will be used
|
|
||||||
transcode-dir: /tmp/transcoder/data
|
|
||||||
|
|
||||||
# Available video profiles
|
|
||||||
# Do not change these
|
|
||||||
video-profiles:
|
|
||||||
360p:
|
|
||||||
width: 640 # px
|
|
||||||
height: 360 # px
|
|
||||||
bitrate: 800 # kbps
|
|
||||||
480p:
|
|
||||||
width: 640
|
|
||||||
height: 480
|
|
||||||
bitrate: 1200
|
|
||||||
720p:
|
|
||||||
width: 1280
|
|
||||||
height: 720
|
|
||||||
bitrate: 2800
|
|
||||||
1080p:
|
|
||||||
width: 1920
|
|
||||||
height: 1080
|
|
||||||
bitrate: 5000
|
|
||||||
|
|
||||||
# Use video keyframes as existing reference for chunks split
|
|
||||||
# Using this might cause long probing times in order to get
|
|
||||||
# all keyframes - therefore they should be cached
|
|
||||||
video-keyframes: false
|
|
||||||
|
|
||||||
# Single audio profile used
|
|
||||||
audio-profile:
|
|
||||||
bitrate: 192 # kbps
|
|
||||||
|
|
||||||
# If cache is enabled
|
|
||||||
cache: true
|
|
||||||
# If dir is empty, cache will be stored in the same directory as media source
|
|
||||||
# If not empty, cache files will be saved to specified directory
|
|
||||||
cache-dir: /tmp/transcoder/cache
|
|
||||||
|
|
||||||
# OPTIONAL: Use custom ffmpeg & ffprobe binary paths
|
|
||||||
ffmpeg-binary: ffmpeg
|
|
||||||
ffprobe-binary: ffprobe
|
|
Loading…
Reference in New Issue