Initial commit
This commit is contained in:
commit
abb80b89af
12
README
Normal file
12
README
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
With this utility it is possible to record live streams that is available through a Restreamer instance.
|
||||||
|
This monitors the Restreamer API to check if the local repeater is connected. When it is, it probes the
|
||||||
|
HLS endpoint and depending on the HTTP Code in the response it starts an FFmpeg process that copies the
|
||||||
|
HLS output to a specified location on the filesystem. Then it can be played back.
|
||||||
|
It is also possible to provide a "rewindable" live stream, but keep in mind that it will introduce big
|
||||||
|
latency.
|
||||||
|
|
||||||
|
To set this up, clone this repository and move or copy config.example.json to config.json, then edit it.
|
||||||
|
Then, run the following command to start monitoring and recording streams: php -q /path/to/record.php
|
||||||
|
|
||||||
|
Create a cronjob or systemd service to make it run on boot and handle potential failures/exits.
|
||||||
|
Example cronjob: * * * * * flock -n /tmp/hls-recorder-flock -c "php -q /path/to/record.php" &
|
8
config.example.json
Normal file
8
config.example.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"vod":"\/home\/example\/web\/uploads",
|
||||||
|
"api":"http:\/\/127.0.0.1:8080\/v1",
|
||||||
|
"hls":"http:\/\/127.0.0.1:8080\/hls\/live.stream.m3u8",
|
||||||
|
"pid":"\/home\/example\/hls-recorder\/ffmpeg-flock",
|
||||||
|
"mail":["info@example.org","dir@example.org"],
|
||||||
|
"loglevel":1
|
||||||
|
}
|
90
record.php
Normal file
90
record.php
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
if (!file_exists(__DIR__.'/config.json'))
|
||||||
|
logger(1, 'Config file not found', 1, true);
|
||||||
|
|
||||||
|
if (!$_set = @json_decode(@file_get_contents(__DIR__.'/config.json')))
|
||||||
|
logger(1, 'Unable to load or parse configuration file', 1, true);
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// Basic functions
|
||||||
|
function logger($tabs = 1, $txt, $lvl = 1, $exit = false)
|
||||||
|
{
|
||||||
|
global $_set;
|
||||||
|
|
||||||
|
if ($lvl >= $_set->loglevel)
|
||||||
|
echo "[".date('Y-m-d H:i:s')."]".str_repeat("\t", $tabs)."$txt\n";
|
||||||
|
if ($exit)
|
||||||
|
exit;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function is_dir_empty($dir) {
|
||||||
|
if (!is_readable($dir)) return NULL;
|
||||||
|
return (count(scandir($dir)) == 2);
|
||||||
|
}
|
||||||
|
function notify($sub, $msg, $loglevel = 1)
|
||||||
|
{
|
||||||
|
global $_set;
|
||||||
|
|
||||||
|
if (is_array($_set->mail) && !empty($_set->mail))
|
||||||
|
foreach ($_set->mail AS $mail)
|
||||||
|
if (!@mail($mail, "=?UTF-8?B?".base64_encode('[hls-recorder] '.$sub)."?=", $msg, "Content-type: text/plain; charset=utf-8"))
|
||||||
|
logger($loglevel, 'Unable to send notification E-mail');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop indefinitely
|
||||||
|
while (true) :
|
||||||
|
|
||||||
|
if ($api = @file_get_contents($_set->api.'/states'))
|
||||||
|
if ($api = @json_decode($api))
|
||||||
|
if (isset($api->repeat_to_local_nginx) && $api->repeat_to_local_nginx->type == 'connected')
|
||||||
|
{
|
||||||
|
logger(1, 'Repeater seems to be connected');
|
||||||
|
|
||||||
|
$handle = curl_init($_set->hls);
|
||||||
|
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
|
||||||
|
$response = curl_exec($handle);
|
||||||
|
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
|
||||||
|
curl_close($handle);
|
||||||
|
if ($httpCode == 200)
|
||||||
|
{
|
||||||
|
$output_directory = $_set->vod.'/vod-'.date('Ymd-His');
|
||||||
|
$exitcode = 0;
|
||||||
|
|
||||||
|
if (@mkdir($output_directory))
|
||||||
|
{
|
||||||
|
logger(2, 'All checks passed, starting ffmpeg');
|
||||||
|
notify('Recording', 'Restreamer API reported that repeating to local nginx is connected and the HLS endpoint is found. The HLS output is now being recorded. HLS URL is the following: '.$_set->hls.', Output directory is: '.$output_directory, 2);
|
||||||
|
exec('flock -n '.$_set->pid.' -c "ffmpeg -i '.$_set->hls.' -c copy '.$output_directory.'/index.m3u8 2> '.$output_directory.'/ffmpeg.log"', $output, $exitcode);
|
||||||
|
logger(2, 'ffmpeg exited with code '.$exitcode);
|
||||||
|
notify('Recording stopped', 'The FFMPEG process shut down with exit code: '.$exitcode, 2);
|
||||||
|
if ($exitcode)
|
||||||
|
{
|
||||||
|
logger(3, 'Non-clean exit (expected), checking if output directory is empty');
|
||||||
|
if (is_dir_empty($output_directory))
|
||||||
|
if (@rmdir($output_directory))
|
||||||
|
logger(4, 'Output directory removed');
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger(4, 'Unable to remove output directory');
|
||||||
|
notify('Error', 'The FFMPEG process shut down with exit code '.$exitcode.' and the output directory is empty (nothing recorded). Output directory should have been removed automatically, but the process failed. Remove the output directory manually: '.$output_directory, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
logger(3, 'Unable to create output directory');
|
||||||
|
} else
|
||||||
|
logger(2, 'HLS inaccessible, HTTP Code '.$httpCode);
|
||||||
|
|
||||||
|
} else
|
||||||
|
logger(1, 'Repeater not in connected state', 0);
|
||||||
|
else
|
||||||
|
logger(1, 'API response unreadable');
|
||||||
|
else
|
||||||
|
logger(1, 'API can not be accessed');
|
||||||
|
|
||||||
|
sleep(5);
|
||||||
|
|
||||||
|
endwhile;
|
Loading…
Reference in New Issue
Block a user