Selfhosted alternativa k Vimeo

Vimeo je skvělá služba, kterou klientům často doporučuji pro embedování videí na jejich webu. Placený účet na Vimeo totiž umožňuje jednoduše nastavovat oprávnění pro přístup k videím, omezit domény, kde je možné videa vkládat atd.

Pokud ale máte hodně videí, služba může být poměrně drahá. Pro klienta, který za hostování svých videí u Vimeo platil 150 000,- Kč / rok, jsem tedy hledal alternativu, která by umožňovala podobnou úroveň zabezpečení a která by nabízela levnější dlouhodobý provoz.

Open source systémů na hostování videí existuje spousta, nakonec jsem se ale rozhodl pro kombinaci systémů, které umožňují opravdovou flexibilitu.

Pro ukládání videí je možné využít Minio, což je v podstatě selfhosted alternativa k úložišti Amazon S3. Větší videa je potřeba streamovat po částech, na to je možné využít několik formátů, jedním z nich je HLS. Ten mimo jiné podporuje i videa v několika rozlišeních, ze kterých si uživatel může buď vybrat, nebo se automaticky použijí dle aktuální rychlosti internetu. Pro převod MP4 na HLS je možné využít open-source knihovnu FFMPEG. Jako přehrávač jsem se rozhodl použít skvělou knihovnu Video.js, která podporuje stremovací formát HLS, s několika pluginy (např. na náhledy videa nebo přepínání kvality).

Aby bylo možné videa na web vkládat, připravil jsem plugin, který přidá Gutenberg pro jednoduché vložení videa.

Jak to tedy funguje?
Video v MP4 je potřeba nejprve převést na HLS. To se dá udělat pomocí FFMPEG přibližně takto:

ffmpeg -i "test.mp4" -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -c:v libx264 -crf 22 -c:a aac -ar 48000 -filter:v:0 scale=w=480:h=360  -maxrate:v:0 600k -b:a:0 64k -filter:v:2 scale=w=1280:h=720 -maxrate:v:2 900k -b:a:2 128k -var_stream_map "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p" -preset fast -hls_list_size 0 -threads 0 -f hls -hls_playlist_type event -hls_time 3 -hls_flags independent_segments -master_pl_name "test.m3u8" "test-%v.m3u8"   /Users/vaclavgreif/Desktop/generator

Výsledkem je video rozdělené po 6s na mnoho souborů, ve dvou rozlišeních.

Videa se nahrají do úložiště minio, které umožňuje nastavit souborům a složkám různá oprávnění. Pro naše potřeby nastavíme, že složka je soukromá a není přístupná zvenku. Protože je ale MINIo kompatibilní s Amazon AWS, je možné použít AWS PHP SDK a vytvořit dynamickou pre-signed URL, která soubor na určitou dobu (v našem případě 30s) zpřístupní:

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Aws\S3\S3Client;
use Aws\Exception\AwsException;

require_once __DIR__ . '/s3-config.php';
$options = json_decode( $options, true);
$s3      = new Aws\S3\S3Client( [
	'version'     => 'latest',
	'region'      => 'us-east-1',
	'endpoint'    => $options['s3_url'],
	'credentials' => [
		'key'    => $options['s3_key'],
		'secret' => $options['s3_secret'],
	],
] );

$cmd = $s3->getCommand( 'GetObject', [
	'Bucket' => $_GET['bucket'],
	'Key'    => $_GET['file']
] );

$request = $s3->createPresignedRequest( $cmd, '+30 seconds' );
echo json_encode( [
	'uri' => $request->getUri()->__toString()
] );

Přehrávač Video.js podporuje HLS, tzn. že mu je možné dát m3u8 playlist, který obsahuje adresy souborů s částmi videa, a přehrávač jednotlivé části postupně načítá. Protože ale soubory nejsou veřejně přístupné, je potřeba nahradit URL souboru za presigned url, která k souboru umožní přístup. Tato adresa se volá pro každou část videa a vrátí presigned URL, na které je soubor po dobu 30s dostupný.

const handlePlayerReady = (player) => {
		playerRef.current = player;
		
		const playerXhrRequestHook = (options) => {
			const file = options.uri.replace('http://127.0.0.1:9000/', '');

			const result = synchronousRequest(addQueryArgs(window.wpify_protected_video.sign_url, {file, bucket}));
			options.uri = JSON.parse(result).uri;
			return options;
		};
		playerRef.current.tech().vhs.xhr.onRequest(playerXhrRequestHook);
	};

Výsledkem je plně funkční přehrávač, který podporuje streamování různých kvalit videa, je kompatibilní s drtivou většinou zařízení, nabízí vysokou úroveň zabezpečení, dá se jednoduše provozovat na vlastním serveru a dokáže odbavit stovky simultáních uživatelů . Náklady na provoz takového řešení jsou pro 3TB videí okolo 40 000,- Kč / rok, tedy přibližně čtvrtinu nákladů na účet u Vimea.

Pokud potřebujete pomoci s alternativou k Vimeo nebo s řešeními na míru pro WordPress, neváhejte mě kontaktovat

Přidat komentář