1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-03 01:39:24 +02:00
Oinktube/plugin/Live/restreamer.json.php
akhilleusuggo e48e30fd67
Update restreamer.json.php
-re is mandatory on every live-stream . Because the speed will be dancing between x0.5 and x2 . Should be fixed to real time = x1
I'm still debugging somethings , but this one is necessary .
2020-09-03 08:00:19 +03:00

254 lines
10 KiB
PHP

<?php
/**
* This file intent to restream your lives, you can copy this file in any server with FFMPEG
* Make sure you add the correct path to this file on the Live plugin restreamerURL parameter
*
* If you want to restream to Facebook, make sure your FFMPEG is compiled with openssl support
* On Ubuntu you can install like this:
* apt-get -y install build-essential autoconf automake cmake libtool git checkinstall nasm yasm libass-dev libfreetype6-dev libsdl2-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-dev libchromaprint-dev frei0r-plugins-dev ladspa-sdk libcaca-dev libcdio-paranoia-dev libcodec2-dev libfontconfig1-dev libfreetype6-dev libfribidi-dev libgme-dev libgsm1-dev libjack-dev libmodplug-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libopenjp2-7-dev libopenmpt-dev libopus-dev libpulse-dev librsvg2-dev librubberband-dev librtmp-dev libshine-dev libsmbclient-dev libsnappy-dev libsoxr-dev libspeex-dev libssh-dev libtesseract-dev libtheora-dev libtwolame-dev libv4l-dev libvo-amrwbenc-dev libvpx-dev libwavpack-dev libwebp-dev libx264-dev libx265-dev libxvidcore-dev libxml2-dev libzmq3-dev libzvbi-dev liblilv-dev libmysofa-dev libopenal-dev opencl-dev gnutls-dev libfdk-aac-dev
* git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg && cd ffmpeg
* ./configure --disable-shared --enable-static --enable-pthreads --enable-gpl --enable-nonfree --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-filters --enable-openssl --enable-runtime-cpudetect --extra-version=patrickz
* make
* make install
*/
$streamerURL = "https://demo.avideo.com/"; // change it to your streamer URL
// optional you can change the log file location here
$logFileLocation = '/var/www/tmp/';
/**
* $separateRestreams if it is set to true the script will use one FFMPEG command/process for each restream, otherwise will use only one for all streams
* all in one FFMPEG command will save you CPU and other resources, but will make harder to find issues
*/
$separateRestreams = false;
// optional you can change the default FFMPEG
//$ffmpegBinary = '/usr/bin/ffmpeg';
$ffmpegBinary = '/usr/local/bin/ffmpeg';
/*
* DO NOT EDIT AFTER THIS LINE
*/
set_time_limit(300);
ini_set('max_execution_time', 300);
$logFileLocation = rtrim($logFileLocation, "/") . '/';
$logFile = $logFileLocation . "ffmpeg_{users_id}_" . date("Y-m-d-h-i-s") . ".log";
header('Content-Type: application/json');
$configFile = '../../videos/configuration.php';
if (file_exists($configFile)) {
include_once $configFile;
$streamerURL = $global['webSiteRootURL'];
}
error_log("Restreamer.json.php start");
$whichffmpeg = whichffmpeg();
if($whichffmpeg!==$ffmpegBinary){
error_log("Restreamer.json.php WARNING you are using a different FFMPEG $whichffmpeg!==$ffmpegBinary");
}
$request = file_get_contents("php://input");
error_log("Restreamer.json.php php://input {$request}");
$robj = json_decode($request);
$obj = new stdClass();
$obj->error = true;
$obj->msg = "";
$obj->streamerURL = $streamerURL;
$obj->token = $robj->token;
$obj->pid = array();
$obj->logFile = str_replace('{users_id}', $robj->users_id, $logFile);
if (empty($robj->restreamsDestinations) || !is_array($robj->restreamsDestinations)) {
$obj->msg = "There are no restreams Destinations";
error_log("Restreamer.json.php ERROR {$obj->msg}");
die(json_encode($obj));
}
error_log("Restreamer.json.php Found " . count($robj->restreamsDestinations) . " destinations: " . json_encode($robj->restreamsDestinations));
// check the token
if (empty($obj->token)) {
$obj->msg = "Token is empty";
error_log("Restreamer.json.php ERROR {$obj->msg}");
die(json_encode($obj));
}
$verifyTokenURL = "{$obj->streamerURL}plugin/Live/verifyToken.json.php?token={$obj->token}";
error_log("Restreamer.json.php verifying token {$verifyTokenURL}");
$content = file_get_contents($verifyTokenURL);
error_log("Restreamer.json.php verification respond content {$content}");
$json = json_decode($content);
if (empty($json)) {
$obj->msg = "Could not verify token";
error_log("Restreamer.json.php ERROR {$obj->msg} ({$verifyTokenURL}) ");
die(json_encode($obj));
} else if (!empty($json->error)) {
$obj->msg = "Token is invalid";
error_log("Restreamer.json.php ERROR {$obj->msg} ({$verifyTokenURL}) " . json_encode($json));
die(json_encode($obj));
}
error_log("Restreamer.json.php token is correct");
ignore_user_abort(true);
ob_start();
header("Connection: close");
@header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();
if (empty($separateRestreams)) {
error_log("Restreamer.json.php all in one command ");
$obj->pid[] = startRestream($robj->m3u8, $robj->restreamsDestinations, $obj->logFile);
} else {
error_log("Restreamer.json.php separateRestreams " . count($robj->restreamsDestinations));
foreach ($robj->restreamsDestinations as $key => $value) {
sleep(0.5);
$obj->pid[] = startRestream($robj->m3u8, array($value), str_replace(".log", "_{$key}.log", $obj->logFile));
}
}
$obj->error = false;
error_log("Restreamer.json.php finish " . json_encode($obj));
die(json_encode($obj));
function clearCommandURL($url) {
return preg_replace('/[^0-9a-z:.\/_&?=-]/i', "", $url);
}
function isURL200($url) {
error_log("Restreamer.json.php checking URL {$url}");
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
error_log("Restreamer.json.php URL {$url} return code {$httpcode}");
return $httpcode == 200;
}
function startRestream($m3u8, $restreamsDestinations, $logFile, $tries = 1) {
global $ffmpegBinary;
if (empty($restreamsDestinations)) {
error_log("Restreamer.json.php ERROR empty restreamsDestinations");
return false;
}
$m3u8 = clearCommandURL($m3u8);
killIfIsRunning($m3u8);
if (!isURL200($m3u8)) {
if ($tries > 10) {
error_log("Restreamer.json.php tried too many times, we could not find your stream URL");
return false;
}
error_log("Restreamer.json.php URL is not ready. trying again ({$tries})");
sleep($tries);
return startRestream($m3u8, $restreamsDestinations, $logFile, $tries + 1);
}
/*
$command = "ffmpeg -i {$m3u8} ";
foreach ($restreamsDestinations as $value) {
$value = clearCommandURL($value);
$command .= ' -max_muxing_queue_size 1024 -f flv "' . $value . '" ';
}
*
*/
if (count($restreamsDestinations) > 1) {
$command = "{$ffmpegBinary} -re -i \"{$m3u8}\" ";
foreach ($restreamsDestinations as $value) {
if(!isOpenSSLEnabled() && preg_match("/rtpms:/i", $value)){
error_log("Restreamer.json.php ERROR #1 FFMPEG openssl is not enabled, ignoring $value ");
continue;
}
$value = clearCommandURL($value);
$command .= ' -max_muxing_queue_size 1024 -acodec copy -bsf:a aac_adtstoasc -vcodec copy -f flv "' . $value . '" ';
}
} else {
if(!isOpenSSLEnabled() && preg_match("/rtpms:/i", $restreamsDestinations[0])){
error_log("Restreamer.json.php ERROR #2 FFMPEG openssl is not enabled, ignoring {$restreamsDestinations[0]} ");
}else{
$command = "ffmpeg -re -i \"{$m3u8}\" -max_muxing_queue_size 1024 -acodec copy -bsf:a aac_adtstoasc -vcodec copy -f flv \"{$restreamsDestinations[0]}\"";
}
}
if(empty($command) || !preg_match("/-f flv/i", $command)){
error_log("Restreamer.json.php ERROR command is empty ");
}else{
error_log("Restreamer.json.php startRestream {$command}, check the file ($logFile) for the log");
exec('echo \'' . $command . PHP_EOL . '\' > ' . $logFile);
exec('nohup ' . $command . ' 2>> ' . $logFile . ' > /dev/null &');
error_log("Restreamer.json.php startRestream finish");
}
return true;
}
$isOpenSSLEnabled = null;
function isOpenSSLEnabled() {
global $isOpenSSLEnabled, $ffmpegBinary;
if(isset($isOpenSSLEnabled)){
return $isOpenSSLEnabled;
}
exec("{$ffmpegBinary} 2>&1", $output, $return_var);
foreach ($output as $value) {
if (preg_match("/configuration:.*--enable-openssl/i", $value)) {
$isOpenSSLEnabled = true;
return $isOpenSSLEnabled;
}
}
$isOpenSSLEnabled = false;
return $isOpenSSLEnabled;
}
function whichffmpeg() {
exec("which ffmpeg 2>&1", $output, $return_var);
return @$output[0];
}
function getProcess($m3u8){
$m3u8 = clearCommandURL($m3u8);
global $ffmpegBinary;
exec("ps -ax 2>&1", $output, $return_var);
//error_log("Restreamer.json.php:getProcess ". json_encode($output));
foreach ($output as $value) {
$pattern = "/^([0-9]+).*".replaceSlashesForPregMatch($ffmpegBinary).".*".replaceSlashesForPregMatch($m3u8)."/i";
//error_log("Restreamer.json.php:getProcess {$pattern}");
if (preg_match($pattern, trim($value), $matches)) {
return $matches;
}
}
return false;
}
function killIfIsRunning($m3u8){
$process = getProcess($m3u8);
error_log("Restreamer.json.php killIfIsRunning checking if there is a process running for {$m3u8} ");
if(!empty($process)){
error_log("Restreamer.json.php killIfIsRunning there is a process running for {$m3u8} ". json_encode($process));
$pid = intval($process[1]);
if(!empty($pid)){
error_log("Restreamer.json.php killIfIsRunning killing {$pid} ");
exec("kill -9 {$pid} 2>&1", $output, $return_var);
sleep(1);
}
return true;
}else{
error_log("Restreamer.json.php killIfIsRunning there is not a process running for {$m3u8} ");
}
return false;
}
function replaceSlashesForPregMatch($str){
return str_replace('/', '.', $str);
}