urmic_digital_encoder_decoder/encoder/static.php

1539 lines
60 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*
Urmi you happy me happy licence
Copyright (c) 2026 shreebhattji
License text:
https://github.com/shreebhattji/Urmi/blob/main/licence.md
*/
function toVppScale($resolution, $default = "w=1280:h=720")
{
if (preg_match('/^\s*(\d+)\s*[x×]\s*(\d+)\s*$/', $resolution, $m)) {
return "w={$m[1]}:h={$m[2]}";
}
return $default;
}
function generateRandomString($length = 16)
{
$bytes = random_bytes(ceil($length / 2));
$randomString = bin2hex($bytes);
return substr($randomString, 0, $length);
}
function setptsFromMs($ms)
{
// convert ms → seconds
$sec = $ms / 1000;
// format with up to 3 decimals (avoid scientific notation)
$secFormatted = number_format($sec, 3, '.', '');
return 'setpts=PTS+' . $secFormatted . '/TB';
}
function adelayFromMs($ms, $channels = 2)
{
// build "ms|ms|ms..." pattern for each audio channel
$parts = array_fill(0, $channels, (string)$ms);
$pattern = implode('|', $parts);
return 'adelay=' . $pattern;
}
function deleteDir(string $dir): void
{
if (!is_dir($dir)) return;
$it = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($files as $file) {
$file->isDir() ? rmdir($file->getRealPath()) : unlink($file->getRealPath());
}
rmdir($dir);
}
function find_first_physical_ethernet(): ?string
{
foreach (scandir('/sys/class/net') as $iface) {
if ($iface === '.' || $iface === '..' || $iface === 'lo') {
continue;
}
$net = "/sys/class/net/$iface";
if (!is_link("$net/device")) {
continue;
}
$type = @trim(file_get_contents("$net/type"));
if ($type !== '1') {
continue;
}
if (is_dir("$net/wireless")) {
continue;
}
if (is_dir("$net/bridge")) {
continue;
}
$addrAssignType = @trim(file_get_contents("$net/addr_assign_type"));
if ($addrAssignType !== '0') {
continue;
}
return $iface;
}
return null;
}
function build_interface(array $cfg, string $type): array
{
$out = [];
/* ---------- IPv4 ---------- */
if ($cfg['mode'] === 'dhcp') {
$out['dhcp4'] = true;
} elseif ($cfg['mode'] === 'static') {
$out['dhcp4'] = false;
if ($cfg["network_{$type}_ip"] !== '') {
$out['addresses'][] = $cfg["network_{$type}_ip"]; // already CIDR
}
if ($cfg["network_{$type}_gateway"] !== '') {
$out['gateway4'] = $cfg["network_{$type}_gateway"];
}
$dns = array_filter([
$cfg["network_{$type}_dns1"],
$cfg["network_{$type}_dns2"]
]);
if ($dns) {
$out['nameservers']['addresses'] = array_values($dns);
}
} else {
$out['dhcp4'] = false;
}
/* ---------- IPv6 ---------- */
if ($cfg['modev6'] === 'auto') {
$out['dhcp6'] = true;
$out['accept-ra'] = true;
} elseif ($cfg['modev6'] === 'dhcpv6') {
$out['dhcp6'] = true;
$out['accept-ra'] = false;
} elseif ($cfg['modev6'] === 'static') {
$out['dhcp6'] = false;
$out['accept-ra'] = false;
if (
$cfg["network_{$type}_ipv6"] !== '' &&
$cfg["network_{$type}_ipv6_prefix"] !== ''
) {
$out['addresses'][] =
$cfg["network_{$type}_ipv6"] . '/' .
$cfg["network_{$type}_ipv6_prefix"];
}
if ($cfg["network_{$type}_ipv6_gateway"] !== '') {
$out['gateway6'] = $cfg["network_{$type}_ipv6_gateway"];
}
$dns6 = array_filter([
$cfg["network_{$type}_ipv6_dns1"],
$cfg["network_{$type}_ipv6_dns2"]
]);
if ($dns6) {
$out['nameservers']['addresses'] =
array_merge($out['nameservers']['addresses'] ?? [], $dns6);
}
} else {
$out['dhcp6'] = false;
$out['accept-ra'] = false;
}
return $out;
}
function generate_netplan(array $data, string $iface): array
{
$netplan = [
'network' => [
'version' => 2,
'renderer' => 'networkd',
'ethernets' => [],
'vlans' => []
]
];
/* ---------- BASE INTERFACE (PRIMARY FIRST) ---------- */
if (
$data['primary']['mode'] !== 'disabled' ||
$data['primary']['modev6'] !== 'disabled'
) {
$base_vlan = trim($data['primary']['network_primary_vlan'] ?? '');
if ($base_vlan === '') {
// Configure base NIC
$netplan['network']['ethernets'][$iface] =
build_interface($data['primary'], 'primary');
}
}
/* ---------- BASE INTERFACE (SECONDARY ONLY IF NOT SET) ---------- */
if (
!isset($netplan['network']['ethernets'][$iface]) &&
(
$data['secondary']['mode'] !== 'disabled' ||
$data['secondary']['modev6'] !== 'disabled'
)
) {
$base_vlan = trim($data['secondary']['network_secondary_vlan'] ?? '');
if ($base_vlan === '') {
$netplan['network']['ethernets'][$iface] =
build_interface($data['secondary'], 'secondary');
}
}
/* ---------- VLANs (PRIMARY) ---------- */
$p_vlan = trim($data['primary']['network_primary_vlan'] ?? '');
if ($p_vlan !== '') {
// Ensure base interface exists
$netplan['network']['ethernets'][$iface] ??= new stdClass();
$netplan['network']['vlans']["{$iface}.{$p_vlan}"] =
array_merge(
['id' => (int)$p_vlan, 'link' => $iface],
build_interface($data['primary'], 'primary')
);
}
/* ---------- VLANs (SECONDARY) ---------- */
$s_vlan = trim($data['secondary']['network_secondary_vlan'] ?? '');
if ($s_vlan !== '') {
$netplan['network']['ethernets'][$iface] ??= new stdClass();
$netplan['network']['vlans']["{$iface}.{$s_vlan}"] =
array_merge(
['id' => (int)$s_vlan, 'link' => $iface],
build_interface($data['secondary'], 'secondary')
);
}
/* ---------- Normalize vlans ---------- */
if (empty($netplan['network']['vlans'])) {
$netplan['network']['vlans'] = new stdClass();
}
return $netplan;
}
function validate_config(array $data): bool
{
$p_enabled = (
$data['primary']['mode'] !== 'disabled' ||
$data['primary']['modev6'] !== 'disabled'
);
$s_enabled = (
$data['secondary']['mode'] !== 'disabled' ||
$data['secondary']['modev6'] !== 'disabled'
);
$p_vlan = trim($data['primary']['network_primary_vlan'] ?? '');
$s_vlan = trim($data['secondary']['network_secondary_vlan'] ?? '');
/* If both enabled → at least one VLAN required */
if ($p_enabled && $s_enabled && $p_vlan === '' && $s_vlan === '') {
echo "<script>alert('Primary and Secondary are enabled, but no VLAN is defined.');</script>";
return false;
}
/* Block duplicate VLAN IDs */
if ($p_vlan !== '' && $s_vlan !== '' && $p_vlan === $s_vlan) {
echo "<script>alert('Primary and Secondary cannot use the same VLAN ID.');</script>";
return false;
}
return true;
}
function netplan_yaml(array $data, int $indent = 0): string
{
$out = '';
$pad = str_repeat(' ', $indent);
foreach ($data as $key => $value) {
if ($value instanceof stdClass) {
$out .= "{$pad}{$key}: {}\n";
continue;
}
if (is_bool($value)) {
$out .= "{$pad}{$key}: " . ($value ? 'true' : 'false') . "\n";
continue;
}
if (!is_array($value)) {
$out .= "{$pad}{$key}: {$value}\n";
continue;
}
if (array_keys($value) === range(0, count($value) - 1)) {
$out .= "{$pad}{$key}:\n";
foreach ($value as $item) {
$out .= "{$pad} - {$item}\n";
}
continue;
}
$out .= "{$pad}{$key}:\n";
$out .= netplan_yaml($value, $indent + 1);
}
return $out;
}
function update_service($which_service)
{
if ($which_service == 'input') {
exec("sudo systemctl stop encoder-main");
exec("sudo systemctl disable encoder-main");
exec("sudo modprobe -r uvcvideo && sudo modprobe uvcvideo");
}
$input = "";
$input_source = "";
$input_rtmp_mount = "";
$input_rtmp_pass = "";
$output = "";
$srt_pass1 = "";
$srt_pass2 = "";
$srt_pass3 = "";
$rtmp0_multiple[] = [];
$rtmp1_multiple[] = [];
$srt_multiple[] = [];
$input_transcode_every_time = 'https://cdn.urmic.org/unavailable.mp4';
$defaults = [
'input' => 'url',
'use_common_backend' => 'use_common_backend',
'hdmi' => [
'resolution' => '1920x1080',
'audio_source' => 'hw:1,0',
'framerate' => '30',
'video_delay' => '',
'audio_delay' => '',
'brightness' => '0',
'contrast' => '1',
'saturation' => '1',
'hue' => '0',
],
'url' => 'https://cdn.urmic.org/unavailable.mp4',
'rtmp' => [
'mount' => 'channel_name',
'password' => 'live',
],
'srt' => [
'stream_id_1' => 'forever',
'stream_id_2' => 'steaming',
'stream_id_3' => 'partner',
],
'udp' => 'udp://@224.1.1.1:8000',
'custom' => '',
'common_backend' => [
'resolution' => '1920x1080',
'data_rate' => '5M',
'framerate' => '30',
'gop' => '30',
'audio_db_gain' => '0dB',
'audio_data_rate' => '128k',
'audio_sample_rate' => '48000',
'extra' => ''
],
];
$jsonFile = __DIR__ . '/input.json';
if (file_exists($jsonFile)) {
$raw = file_get_contents($jsonFile);
$data = json_decode($raw, true);
if (!is_array($data)) $data = $defaults;
$data = array_replace_recursive($defaults, $data);
} else {
$data = $defaults;
}
$input_source = $data['input'];
$use_common_backend = $data['use_common_backend'];
$input_rtmp_mount = $data['rtmp']['mount'];
$input_rtmp_pass = $data['rtmp']['password'];
$srt_pass1 = $data['srt']['stream_id_1'];
$srt_pass2 = $data['srt']['stream_id_2'];
$srt_pass3 = $data['srt']['stream_id_3'];
$common_backend_resolution = $data['common_backend']['resolution'];
$common_backend_data_rate = $data['common_backend']['data_rate'];
$common_backend_framerate = $data['common_backend']['framerate'];
$common_backend_gop = $data['common_backend']['gop'];
$common_backend_audio_db_gain = $data['common_backend']['audio_db_gain'];
$common_backend_audio_data_rate = $data['common_backend']['audio_data_rate'];
$common_backend_audio_sample_rate = $data['common_backend']['audio_sample_rate'];
$common_backend_extra = $data['common_backend']['extra'];
$common_backend_resolution_vpp = toVppScale($common_backend_resolution);
$common_backend_resolution = str_replace("x", ":", $common_backend_resolution);
$hdmi_delay_video = $data['hdmi']['video_delay'];
$hdmi_delay_audio = $data['hdmi']['audio_delay'];
$hdmi_brightness = $data['hdmi']['brightness'];
$hdmi_contrast = $data['hdmi']['contrast'];
$hdmi_saturation = $data['hdmi']['saturation'];
$hdmi_hue = $data['hdmi']['hue'];
if ($srt_pass1 == "")
$srt_pass1 = generateRandomString(16);
if ($srt_pass2 == "")
$srt_pass2 = generateRandomString(16);
switch ($use_common_backend) {
case "copy_input":
switch ($input_source) {
case "hdmi":
$input .= "ffmpeg -hide_banner -init_hw_device qsv=hw -filter_hw_device hw -hwaccel qsv -hwaccel_output_format qsv -c:v mjpeg_qsv -f v4l2 -thread_queue_size 128 -use_wallclock_as_timestamps 1 -input_format mjpeg "
. " -video_size " . $data['hdmi']['resolution']
. " -framerate " . $data['hdmi']['framerate']
. " -i /dev/video0"
. " -f alsa -thread_queue_size 128 -i " . $data['hdmi']['audio_source']
. " -c:v h264_qsv -profile:v high -level:v 3.1 -global_quality 20 5M -maxrate 5M -bufsize 5M "
. " -c:a aac -b:a 265k -ar 48000 -async 1 -muxrate 0 -pat_period 0.1 -pkt_size 1316 ";
if ($hdmi_delay_video != "")
$input .= ' -vf "vpp_qsv=format=nv12:' . $common_backend_resolution_vpp . ',' . setptsFromMs($hdmi_delay_video) . '"';
else
$input .= ' -vf "vpp_qsv=format=nv12:' . $common_backend_resolution_vpp . '"';
if ($hdmi_delay_audio != "")
$input .= adelayFromMs($hdmi_delay_audio, 2);
$input .= " -f mpegts " . ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "url":
$input .= "ffmpeg -hwaccel auto -hide_banner -stream_loop -1 -re -i " . $data['url'] . " -c:v copy -c:a copy -f mpegts " . ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "udp":
$input .= 'ffmpeg -hwaccel auto -hide_banner -stream_loop -1 -re -i "' . $data['udp'] . " -c:v copy -c:a copy -f mpegts " . ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "rtmp":
$input .= "ffmpeg -hwaccel auto -hide_banner -stream_loop -1 -re -i rtmp://127.0.0.1:1935/" . $input_rtmp_mount . "/" . $input_rtmp_pass . " -c:v copy -c:a copy -f mpegts " . ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "srt":
$input .= "ffmpeg -hwaccel auto -hide_banner -stream_loop -1 -re -i srt://127.0.0.1:1937?streamid=shree/bhatt/" . $srt_pass3 . " -c:v copy -c:a copy -f mpegts " . ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
}
break;
case "use_common_backend":
switch ($input_source) {
case "hdmi":
$input .= "ffmpeg -hide_banner -init_hw_device qsv=hw -filter_hw_device hw -hwaccel qsv -hwaccel_output_format qsv -c:v mjpeg_qsv -f v4l2 -thread_queue_size 128 -use_wallclock_as_timestamps 1 -input_format mjpeg "
. " -video_size " . $data['hdmi']['resolution']
. " -framerate " . $data['hdmi']['framerate'] . " -i /dev/video0 -f alsa -thread_queue_size 128 -i " . $data['hdmi']['audio_source'];
$vf = false;
$vf_input = '';
if ($data['hdmi']['resolution'] != $data['common_backend']['resolution']) {
$vf_input .= ',vpp_qsv=' . $common_backend_resolution_vpp;
$vf = true;
}
if ($hdmi_delay_video != "") {
$vf_input .= ',' . setptsFromMs($hdmi_delay_video);
$vf = true;
}
if ($vf == true) {
$input .= ' -vf "' . $vf_input . '"';
}
$input .= " -c:v h264_qsv -profile:v high -level:v 4.0 -global_quality 20 "
. " -b:v " . $common_backend_data_rate
. " -maxrate " . $common_backend_data_rate
. " -bufsize 1M ";
if ($data['hdmi']['framerate'] != $data['common_backend']['framerate']) {
$input .= " -r " . $common_backend_framerate;
}
$input .=
" -g " . $common_backend_gop
. " -c:a aac "
. " -b:a " . $common_backend_audio_data_rate
. ' -ar ' . $common_backend_audio_sample_rate
. ' ' . $common_backend_extra;
if ($hdmi_delay_audio != "")
$input .= ' -af "aresample=async=1:first_pts=0,volume=' . $common_backend_audio_db_gain . ',' . adelayFromMs($hdmi_delay_audio, 2) . '"';
else
$input .= ' -af "aresample=async=1:first_pts=0,volume=' . $common_backend_audio_db_gain . '"';
$input .= " -fflags nobuffer -flags low_delay -muxrate 0 -muxpreload 0 -pkt_size 1316 -f mpegts "
. ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "url":
$input .= "ffmpeg -hwaccel auto -hide_banner -stream_loop -1 -re -i " . $data['url']
. " -c:v h264_qsv "
. ' -vf "scale=' . $common_backend_resolution . '"'
. " -b:v " . $common_backend_data_rate
. " -maxrate " . $common_backend_data_rate
. " -bufsize 12M"
. " -r " . $common_backend_framerate
. " -g " . $common_backend_gop
. " -c:a aac "
. " -b:a " . $common_backend_audio_data_rate
. ' -af "volume=' . $common_backend_audio_db_gain . '"'
. ' -ar ' . $common_backend_audio_sample_rate
. ' ' . $common_backend_extra . " -tune zerolatency -pkt_size 1316 -f mpegts "
. ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "udp":
$input .= 'ffmpeg -hwaccel auto -hide_banner -stream_loop -1 -re -i "' . $data['udp']
. " -c:v h264_qsv "
. ' -vf "scale=' . $common_backend_resolution . '"'
. " -b:v " . $common_backend_data_rate
. " -maxrate " . $common_backend_data_rate
. " -bufsize 12M"
. " -r " . $common_backend_framerate
. " -g " . $common_backend_gop
. " -c:a aac "
. " -b:a " . $common_backend_audio_data_rate
. ' -af "volume=' . $common_backend_audio_db_gain . '"'
. ' -ar ' . $common_backend_audio_sample_rate
. ' ' . $common_backend_extra . " -tune zerolatency -pkt_size 1316 -f mpegts "
. ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "rtmp":
update_service_backend('rtmp', "", "");
$input .= "ffmpeg -hwaccel auto -hide_banner -stream_loop -1 -re -i rtmp://127.0.0.1:1935/" . $input_rtmp_mount . "/" . $input_rtmp_pass
. " -c:v h264_qsv "
. ' -vf "scale=' . $common_backend_resolution . '"'
. " -b:v " . $common_backend_data_rate
. " -maxrate " . $common_backend_data_rate
. " -bufsize 12M"
. " -r " . $common_backend_framerate
. " -g " . $common_backend_gop
. " -c:a aac "
. " -b:a " . $common_backend_audio_data_rate
. ' -af "volume=' . $common_backend_audio_db_gain . '"'
. ' -ar ' . $common_backend_audio_sample_rate
. ' ' . $common_backend_extra . " -tune zerolatency -pkt_size 1316 -f mpegts "
. ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "srt":
update_service_backend('srt', $srt_pass1, $srt_pass2);
$input .= "ffmpeg -hwaccel auto -hide_banner -stream_loop -1 -re -i srt://127.0.0.1:1937?streamid=shree/bhatt/" . $srt_pass3
. " -c:v h264_qsv "
. ' -vf "scale=' . $common_backend_resolution . '"'
. " -b:v " . $common_backend_data_rate
. " -maxrate " . $common_backend_data_rate
. " -bufsize 12M"
. " -r " . $common_backend_framerate
. " -g " . $common_backend_gop
. " -c:a aac "
. " -b:a " . $common_backend_audio_data_rate
. ' -af "volume=' . $common_backend_audio_db_gain . '"'
. ' -ar ' . $common_backend_audio_sample_rate
. ' ' . $common_backend_extra . " -tune zerolatency -pkt_size 1316 -f mpegts "
. ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
}
break;
case "transcode_every_time":
switch ($input_source) {
case "hdmi":
echo "<script>alert('HDMI can no use same input multiple time');</script>";
break;
case "url":
$input_transcode_every_time = $data['url'];
break;
case "udp":
$input_transcode_every_time = $data['udp'];
break;
case "rtmp":
update_service_backend('rtmp', "", "");
$input_transcode_every_time = "rtmp://127.0.0.1:1935/shree/bhattji";
break;
case "srt":
update_service_backend('srt', $srt_pass1, $srt_pass2);
$input_transcode_every_time = "srt://127.0.0.1:1937?streamid=shree/bhatt/" . $srt_pass3;
break;
}
break;
}
$jsonFile = __DIR__ . '/output.json';
$defaults = [
'service_display' => 'disable',
'service_rtmp0_multiple' => 'disable',
'service_rtmp0_hls' => 'disable',
'service_rtmp0_dash' => 'disable',
'service_rtmp1_multiple' => 'disable',
'service_rtmp1_hls' => 'disable',
'service_rtmp1_dash' => 'disable',
'service_udp0' => 'disable',
'service_udp1' => 'disable',
'service_udp2' => 'disable',
'service_srt_multiple' => 'disable',
'service_custom' => 'disable',
'rtmp0_multiple' => [],
'rtmp1_multiple' => [],
'srt_multiple' => [],
'rtmp0' => [
'common_backend' => 'enable',
'resolution' => '1920x1080',
'data_rate' => '6M',
'framerate' => '30',
'gop' => '30',
'extra' => '',
'audio_data_rate' => '128k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000'
],
'rtmp1' => [
'common_backend' => 'disable',
'resolution' => '720x576',
'data_rate' => '1.5M',
'framerate' => '25',
'gop' => '25',
'extra' => '',
'audio_data_rate' => '96k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000'
],
'udp0' => [
'common_backend' => 'disable',
'udp' => 'udp://@224.1.1.1:8001',
'format' => 'h264_qsv',
'resolution' => '1280x720',
'data_rate' => '2.2M',
'framerate' => '25',
'gop' => '25',
'extra' => '',
'audio_format' => 'aac',
'audio_data_rate' => '128k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000',
'service_udp0_output' => 'default',
'udp0_service_name' => ''
],
'udp1' => [
'common_backend' => 'disable',
'udp' => 'udp://@224.1.1.1:8001',
'format' => 'h264_qsv',
'resolution' => '720x576',
'data_rate' => '1.5M',
'framerate' => '25',
'gop' => '25',
'extra' => '',
'audio_format' => 'mp2',
'audio_data_rate' => '128k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000',
'service_udp1_output' => 'default',
'udp1_service_name' => ''
],
'udp2' => [
'common_backend' => 'disable',
'udp' => 'udp://@224.1.1.1:8002',
'format' => 'mpeg2video',
'resolution' => '720x576',
'data_rate' => '3M',
'framerate' => '25',
'gop' => '25',
'extra' => '',
'audio_format' => 'mp2',
'audio_data_rate' => '96k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000',
'service_udp2_output' => 'default',
'udp2_service_name' => ''
],
'srt' => [
'common_backend' => 'enable',
'format' => 'mpeg2video',
'resolution' => '1920x1080',
'data_rate' => '6M',
'framerate' => '50',
'gop' => '50',
'extra' => '',
'audio_format' => 'aac',
'audio_data_rate' => '256k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000'
],
'display_resolution' => '720x576',
'display_audio' => '0,3',
'display_hdmi_sdi' => 'disable',
'custom_output' => ''
];
for ($i = 1; $i <= 11; $i++) {
$defaults['rtmp0_multiple'][$i] = ['url' => '', 'name' => '', 'enabled' => false];
$defaults['rtmp1_multiple'][$i] = ['url' => '', 'name' => '', 'enabled' => false];
$defaults['srt_multiple'][$i] = ['url' => '', 'name' => '', 'enabled' => false];
}
if (file_exists($jsonFile)) {
$raw = file_get_contents($jsonFile);
$data = json_decode($raw, true);
if (!is_array($data)) $data = $defaults;
$data = array_replace_recursive($defaults, $data);
} else {
$data = $defaults;
}
$service_display = $data['service_display'];
$service_rtmp0_multiple = $data['service_rtmp0_multiple'];
$service_rtmp1_multiple = $data['service_rtmp1_multiple'];
$service_udp0 = $data['service_udp0'];
$service_udp1 = $data['service_udp1'];
$service_udp2 = $data['service_udp2'];
$service_custom = $data['service_custom'];
$service_srt_multiple = $data['service_srt_multiple'];
$rtmp0_multiple = $data['rtmp0_multiple'];
$rtmp1_multiple = $data['rtmp1_multiple'];
$srt_multiple = $data['srt_multiple'];
$display_hdmi_sdi = $data['display_hdmi_sdi'];
$use_common_backend_rtmp0 = $data['rtmp0']['common_backend'];
$use_common_backend_rtmp1 = $data['rtmp1']['common_backend'];
$use_common_backend_udp0 = $data['udp0']['common_backend'];
$use_common_backend_udp1 = $data['udp1']['common_backend'];
$use_common_backend_udp2 = $data['udp2']['common_backend'];
$use_common_backend_srt = $data['srt']['common_backend'];
$display_resolution = $data['display_resolution'];
$display_audio = $data['display_audio'];
switch ($which_service) {
case 'input':
if ($use_common_backend == "") {
exec("sudo systemctl stop encoder-main");
exec("sudo systemctl disable encoder-main");
} else {
$input .= " ";
$control = "v4l2-ctl -d /dev/video0 --set-ctrl=brightness=" . $hdmi_brightness . ';';
$control .= "v4l2-ctl -d /dev/video0 --set-ctrl=contrast=" . $hdmi_contrast . ';';
$control .= "v4l2-ctl -d /dev/video0 --set-ctrl=saturation=" . $hdmi_saturation . ';';
$control .= "v4l2-ctl -d /dev/video0 --set-ctrl=hue=" . $hdmi_hue . ';';
$input = $control . $input;
$file = "/var/www/encoder-main.sh";
if (file_put_contents($file, $input) === false) {
echo "Error writing file.";
}
exec("sudo systemctl enable encoder-main");
exec("sudo systemctl restart encoder-main");
}
break;
case 'display';
$display = "mpv --hwdec=auto --demuxer-lavf-o=fflags=+discardcorrupt --vo=drm --drm-mode=" . $display_resolution . " --fs --keepaspect=no --audio-device=alsa/plughw:" . $display_audio;
if ($display_hdmi_sdi === "enable") {
$display .= ' --audio-format=s16 --audio-samplerate=48000 --audio-channels=stereo --audio-spdif=no';
} else {
$display .= "";
}
if ($service_display === "enable") {
switch ($use_common_backend) {
case "copy_input":
case "use_common_backend":
$display .= ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1"';
break;
case "transcode_every_time":
$display .= ' "' . $input_transcode_every_time . '"';
break;
}
$file = "/var/www/encoder-display.sh";
file_put_contents($file, $display);
exec("sudo systemctl enable encoder-display");
exec("sudo systemctl restart encoder-display");
} else {
exec("sudo systemctl stop encoder-display");
exec("sudo systemctl disable encoder-display");
}
break;
case 'rtmp0';
case 'rtmp1';
update_service_backend("rtmp", "", "");
if ($service_rtmp0_multiple === "enable") {
$rtmp = "ffmpeg -hide_banner -fflags nobuffer -i ";
if ($use_common_backend === "transcode_every_time") {
$rtmp .= $input_transcode_every_time;
} else {
$rtmp .= ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1&overrun_nonfatal=1" ';
switch ($use_common_backend_rtmp0) {
case "enable":
$rtmp .= ' '
. ' -c:v copy '
. ' -c:a aac '
. ' -f flv "rtmp://127.0.0.1/shree/bhattji"';
break;
case "disable":
$rtmp .= ' '
. ' -c:v h264_qsv '
. ' -vf "vpp_qsv=' . $common_backend_resolution_vpp . '"'
. ' -b:v ' . $data['rtmp0']['data_rate']
. ' -maxrate ' . $data['rtmp0']['data_rate']
. ' -bufsize ' . $data['rtmp0']['data_rate']
. ' -r ' . $data['rtmp0']['framerate']
. ' -g ' . $data['rtmp0']['gop']
. ' -c:a aac -b:a ' . $data['rtmp0']['audio_data_rate']
. ' -af "volume=' . $data['rtmp0']['audio_db_gain'] . '"'
. ' -ar ' . $data['rtmp0']['audio_sample_rate']
. ' ' . $data['rtmp0']['extra']
. ' -f flv "rtmp://127.0.0.1/shree/bhattji"';
break;
default:
break;
}
}
if ($use_common_backend_rtmp0 === "disable") {
$rtmp = str_replace("ffmpeg -hwaccel auto -hide_banner -fflags nobuffer -analyzeduration 3000000 -i", "ffmpeg -hwaccel qsv -hwaccel_output_format qsv -hide_banner -fflags nobuffer -analyzeduration 3000000 -i ", $rtmp);
}
$file = "/var/www/encoder-rtmp0.sh";
file_put_contents($file, $rtmp);
exec('sudo systemctl enable encoder-rtmp0');
exec('sudo systemctl restart encoder-rtmp0');
} else {
exec('sudo systemctl stop encoder-rtmp0');
exec('sudo systemctl disable encoder-rtmp0');
}
if ($service_rtmp1_multiple === "enable") {
switch ($use_common_backend_rtmp1) {
case "enable":
$rtmp = 'ffmpeg -hide_banner -fflags nobuffer -i "udp://@239.255.254.254:39000?localaddr=127.0.0.1&overrun_nonfatal=1" '
. ' -c:v copy '
. ' -c:a copy '
. ' -f flv "rtmp://127.0.0.1/shreeshree/bhattji"';
break;
case "disable":
$rtmp = 'ffmpeg -hwaccel auto -hide_banner -fflags nobuffer -analyzeduration 3000000 -i "udp://@239.255.254.254:39000?localaddr=127.0.0.1&overrun_nonfatal=1" '
. ' -c:v h264_qsv '
. ' -vf "vpp_qsv=' . $common_backend_resolution_vpp . '"'
. ' -b:v ' . $data['rtmp1']['data_rate']
. ' -maxrate ' . $data['rtmp1']['data_rate']
. ' -bufsize ' . $data['rtmp1']['data_rate']
. ' -r ' . $data['rtmp1']['framerate']
. ' -g ' . $data['rtmp1']['gop']
. ' -c:a aac -b:a ' . $data['rtmp1']['audio_data_rate']
. ' -af "volume=' . $data['rtmp1']['audio_db_gain'] . '"'
. ' -ar ' . $data['rtmp1']['audio_sample_rate']
. ' ' . $data['rtmp1']['extra']
. ' -f flv "rtmp://127.0.0.1/shreeshree/bhattji"';
break;
default:
break;
}
if ($use_common_backend_rtmp1 === "disable") {
$rtmp = str_replace("ffmpeg -hwaccel auto -hide_banner -fflags nobuffer -analyzeduration 3000000 -i", "ffmpeg -hwaccel qsv -hwaccel_output_format qsv -hide_banner -fflags nobuffer -analyzeduration 3000000 -i ", $rtmp);
}
$file = "/var/www/encoder-rtmp1.sh";
file_put_contents($file, $rtmp);
exec('sudo systemctl enable encoder-rtmp1');
exec('sudo systemctl restart encoder-rtmp1');
} else {
exec('sudo systemctl stop encoder-rtmp1');
exec('sudo systemctl disable encoder-rtmp1');
}
break;
case "srt";
update_service_backend('srt', $srt_pass1, $srt_pass2);
if ($service_srt_multiple) {
$srt = 'ffmpeg -hwaccel auto -hide_banner -fflags +discardcorrupt -i ';
switch ($use_common_backend) {
case "copy_input":
case "use_common_backend":
$srt .= ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1&overrun_nonfatal=1"';
break;
case "transcode_every_time":
$srt .= '"' . $input_transcode_every_time . '"';
break;
}
switch ($use_common_backend_srt) {
case "enable":
$srt .= ' -c copy -mpegts_flags +resend_headers '
. ' -f mpegts "srt://127.0.0.1:1937?streamid=' . $srt_pass1 . '/' . $srt_pass2 . '/ji"';
break;
case "disable":
$srt .= ' -c:v h264_qsv '
. ' -vf "vpp_qsv=' . $common_backend_resolution_vpp . '"'
. ' -b:v ' . $data['srt']['data_rate']
. ' -maxrate ' . $data['srt']['data_rate']
. ' -bufsize ' . $data['srt']['data_rate']
. ' -r ' . $data['srt']['srt']
. ' -g ' . $data['srt']['gop']
. ' -c:a ' . $data['srt']['audio_format']
. ' -b:a ' . $data['srt']['audio_data_rate']
. ' -af "volume=' . $data['srt']['audio_db_gain'] . '"'
. ' -ar ' . $data['srt']['audio_sample_rate']
. ' ' . $data['srt']['extra']
. ' -pkt_size 1316 -flush_packets 0 -f mpegts "srt://127.0.0.1:1937?streamid=' . $srt_pass1 . '/' . $srt_pass2 . '/ji"';
break;
}
$file = "/var/www/encoder-srt.sh";
file_put_contents($file, $srt);
exec('sudo systemctl enable encoder-srt');
exec('sudo systemctl restart encoder-srt');
} else {
exec('sudo systemctl disable srt');
exec('sudo systemctl stop srt');
exec('sudo systemctl disable encoder-srt');
exec('sudo systemctl stop encoder-srt');
}
break;
case "udp0";
if ($service_udp0 === "enable") {
$udp0 = 'ffmpeg -hwaccel auto -hide_banner -i ';
switch ($use_common_backend) {
case "copy_input":
case "use_common_backend":
$udp0 .= ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1&overrun_nonfatal=1"';
break;
case "transcode_every_time":
$udp0 .= '"' . $input_transcode_every_time . '"';
break;
}
switch ($use_common_backend_udp0) {
case "enable":
$udp0 .= ' -c:v copy '
. ' -c:a copy '
. ' -f mpegts "' . $data['udp0']['udp'] . '?pkt_size=1316&ttl=4&buffer_size=1048576"';
break;
case "disable":
$udp0 .= ' -c:v ' . $data['udp0']['format']
. ' -vf "scale=resolution_resolution_resolution"'
. ' -b:v ' . $data['udp0']['data_rate']
. ' -maxrate ' . $data['udp0']['data_rate']
. ' -bufsize ' . $data['udp0']['data_rate']
. ' -r ' . $data['udp0']['framerate']
. ' -g ' . $data['udp0']['gop']
. ' -c:a ' . $data['udp0']['audio_format']
. ' -b:a ' . $data['udp0']['audio_data_rate']
. ' -af "volume=' . $data['udp0']['audio_db_gain'] . '"'
. ' -ar ' . $data['udp0']['audio_sample_rate']
. ' ' . $data['udp0']['extra']
. ' -metadata service_provider=ShreeBhattJI -f mpegts "' . $data['udp0']['udp'] . '?pkt_size=1316&ttl=4&buffer_size=1048576"';
break;
}
if ($use_common_backend == "use_common_backend" && $data['udp0']['format'] == "h264_qsv") {
$udp0 = str_replace("ffmpeg -hwaccel auto -hide_banner -i", "ffmpeg -hwaccel qsv -hwaccel_output_format qsv -hide_banner -i ", $udp0);
$udp0 = str_replace("scale", "vpp_qsv", $udp0);
$udp0 = str_replace("resolution_resolution_resolution", toVppScale($data['udp0']['resolution']), $udp0);
$udp0 = str_replace("h264_qsv", "h264_qsv -profile:v high -level:v 3.1 -global_quality 20 ", $udp0);
} else {
$udp0 = str_replace("resolution_resolution_resolution", str_replace("x", ":", $data['udp0']['resolution']), $udp0);
}
if ($data['udp0']['service_udp0_output'] == "usb") {
$udp0 = str_replace("pkt_size=1316", "pkt_size=1316&localaddr=172.16.111.111", $udp0);
}
if ($data['udp0']['udp0_service_name'] != "") {
$udp0 = str_replace("-f mpegts", "-metadata service_name=" . $data['udp0']['udp0_service_name'] . " -f mpegts", $udp0);
}
if (strpos($udp0, "mpeg2video") !== false) {
$udp0 = str_replace("-hwaccel auto", "", $udp0);
}
$file = "/var/www/encoder-udp0.sh";
file_put_contents($file, $udp0);
exec('sudo systemctl enable encoder-udp0');
exec('sudo systemctl restart encoder-udp0');
} else {
exec('sudo systemctl stop encoder-udp0');
exec('sudo systemctl disable encoder-udp0');
}
break;
case "udp1";
if ($service_udp1 === "enable") {
$udp1 = 'ffmpeg -hwaccel auto -hide_banner -i ';
switch ($use_common_backend) {
case "copy_input":
case "use_common_backend":
$udp1 .= ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1&overrun_nonfatal=1"';
break;
case "transcode_every_time":
$udp1 .= '"' . $input_transcode_every_time . '"';
break;
}
switch ($use_common_backend_udp1) {
case "enable":
$udp1 .= ' -c:v copy '
. ' -c:a copy '
. ' -f mpegts "' . $data['udp1']['udp'] . '?pkt_size=1316&ttl=4&buffer_size=1048576"';
break;
case "disable":
$udp1 .= ' -c:v ' . $data['udp1']['format']
. ' -vf "scale=resolution_resolution_resolution"'
. ' -b:v ' . $data['udp1']['data_rate']
. ' -maxrate ' . $data['udp1']['data_rate']
. ' -bufsize ' . $data['udp1']['data_rate']
. ' -r ' . $data['udp1']['framerate']
. ' -g ' . $data['udp1']['gop']
. ' -c:a ' . $data['udp1']['audio_format']
. ' -b:a ' . $data['udp1']['audio_data_rate']
. ' -af "volume=' . $data['udp1']['audio_db_gain'] . '"'
. ' -ar ' . $data['udp1']['audio_sample_rate']
. ' ' . $data['udp1']['extra']
. ' -metadata service_provider=ShreeBhattJI -f mpegts "' . $data['udp1']['udp'] . '?pkt_size=1316&ttl=4&buffer_size=1048576"';
break;
}
if ($use_common_backend == "use_common_backend" && $data['udp1']['format'] == "h264_qsv") {
$udp1 = str_replace("ffmpeg -hwaccel auto -hide_banner -i", "ffmpeg -hwaccel qsv -hwaccel_output_format qsv -hide_banner -i ", $udp1);
$udp1 = str_replace("scale", "vpp_qsv", $udp1);
$udp1 = str_replace("resolution_resolution_resolution", toVppScale($data['udp1']['resolution']), $udp1);
$udp1 = str_replace("h264_qsv", "h264_qsv -profile:v main -level:v 3.1 -global_quality 20 ", $udp1);
} else {
$udp1 = str_replace("resolution_resolution_resolution", str_replace("x", ":", $data['udp1']['resolution']), $udp1);
}
if ($data['udp1']['service_udp1_output'] === "usb") {
$udp1 = str_replace("pkt_size=1316", "pkt_size=1316&localaddr=172.16.111.111", $udp1);
}
if ($data['udp1']['udp1_service_name'] !== "") {
$udp1 = str_replace("-f mpegts", "-metadata service_name=" . $data['udp1']['udp1_service_name'] . " -f mpegts", $udp1);
}
if (strpos($udp1, "mpeg2video") !== false) {
$udp1 = str_replace("-hwaccel auto", "", $udp1);
}
$file = "/var/www/encoder-udp1.sh";
file_put_contents($file, $udp1);
exec('sudo systemctl enable encoder-udp1');
exec('sudo systemctl restart encoder-udp1');
} else {
exec('sudo systemctl stop encoder-udp1');
exec('sudo systemctl disable encoder-udp1');
}
break;
case "udp2";
$udp2 = 'ffmpeg -hwaccel auto -hide_banner -i ';
switch ($use_common_backend) {
case "copy_input":
case "use_common_backend":
$udp2 .= ' "udp://@239.255.254.254:39000?localaddr=127.0.0.1&overrun_nonfatal=1" ';
break;
case "transcode_every_time":
$udp2 .= '"' . $input_transcode_every_time . '"';
break;
}
if ($service_udp2 === "enable") {
switch ($use_common_backend_udp2) {
case "enable":
$udp2 .= ' -c:v copy '
. ' -c:a copy '
. ' -f mpegts "' . $data['udp2']['udp'] . '?pkt_size=1316&ttl=4&buffer_size=1048576"';
break;
case "disable":
$udp2 .= ' -c:v ' . $data['udp2']['format']
. ' -vf "scale=resolution_resolution_resolution"'
. ' -b:v ' . $data['udp2']['data_rate']
. ' -maxrate ' . $data['udp2']['data_rate']
. ' -bufsize ' . $data['udp2']['data_rate']
. ' -r ' . $data['udp2']['framerate']
. ' -g ' . $data['udp2']['gop']
. ' -c:a ' . $data['udp2']['audio_format']
. ' -b:a ' . $data['udp2']['audio_data_rate']
. ' -af "volume=' . $data['udp2']['audio_db_gain'] . '"'
. ' -ar ' . $data['udp2']['audio_sample_rate']
. ' ' . $data['udp2']['extra']
. ' -metadata service_provider=ShreeBhattJI -f mpegts "' . $data['udp2']['udp'] . '?pkt_size=1316&ttl=4&buffer_size=1048576"';
if ($use_common_backend == "use_common_backend" && $data['udp2']['format'] == "h264_qsv") {
$udp2 = str_replace("ffmpeg -hwaccel auto -hide_banner -i", "ffmpeg -hwaccel qsv -hwaccel_output_format qsv -hide_banner -i ", $udp2);
$udp2 = str_replace("scale", "vpp_qsv", $udp2);
$udp2 = str_replace("resolution_resolution_resolution", toVppScale($data['udp2']['resolution']), $udp2);
$udp2 = str_replace("h264_qsv", "h264_qsv -profile:v main -level:v 3.1 -global_quality 20 ", $udp2);
} else {
$udp2 = str_replace("resolution_resolution_resolution", str_replace("x", ":", $data['udp2']['resolution']), $udp2);
}
if ($data['udp2']['service_udp2_output'] == "usb") {
$udp2 = str_replace("pkt_size=1316", "pkt_size=1316&localaddr=172.16.111.111", $udp2);
}
if ($data['udp2']['udp2_service_name'] != "") {
$udp2 = str_replace("-f mpegts", "-metadata service_name=" . $data['udp2']['udp2_service_name'] . " -f mpegts", $udp2);
}
if (strpos($udp2, "mpeg2video") !== false) {
$udp2 = str_replace("-hwaccel auto", "", $udp2);
}
break;
}
$file = "/var/www/encoder-udp2.sh";
file_put_contents($file, $udp2);
exec('sudo systemctl enable encoder-udp2');
exec('sudo systemctl restart encoder-udp2');
} else {
exec('sudo systemctl stop encoder-udp2');
exec('sudo systemctl disable encoder-udp2');
}
break;
case "custom";
if ($service_custom === "enable") {
$custom = 'ffmpeg -hwaccel auto -hide_banner -i "udp://@239.255.254.254:39000?localaddr=127.0.0.1&overrun_nonfatal=1" '
. $data['custom_output'];
$file = "/var/www/encoder-custom.sh";
file_put_contents($file, $custom);
exec('sudo systemctl enable encoder-custom');
exec('sudo systemctl restart encoder-custom');
} else {
exec('sudo systemctl stop encoder-custom');
exec('sudo systemctl disable encoder-custom');
}
break;
default:
break;
}
}
function update_firewall() {}
function update_firmware() {}
function update_service_backend($service, $srt_pass1, $srt_pass2)
{
$input = "";
$input_source = "";
$input_rtmp_mount = "";
$input_rtmp_pass = "";
$output = "";
$srt_pass3 = "";
$rtmp0_multiple[] = [];
$rtmp1_multiple[] = [];
$srt_multiple[] = [];
$defaults = [
'input' => 'url',
'use_common_backend' => 'use_common_backend',
'hdmi' => [
'resolution' => '1920x1080',
'audio_source' => 'hw:1,0',
'framerate' => '30',
'video_delay' => '',
'audio_delay' => '',
'brightness' => '0',
'contrast' => '1',
'saturation' => '1',
'hue' => '0',
],
'url' => 'https://cdn.urmic.org/unavailable.mp4',
'rtmp' => [
'mount' => 'channel_name',
'password' => 'live',
],
'srt' => [
'stream_id_1' => 'forever',
'stream_id_2' => 'steaming',
'stream_id_3' => 'partner',
],
'udp' => 'udp://@224.1.1.1:8000',
'custom' => '',
'common_backend' => [
'resolution' => '1920x1080',
'data_rate' => '5M',
'framerate' => '30',
'gop' => '30',
'audio_db_gain' => '0dB',
'audio_data_rate' => '128k',
'audio_sample_rate' => '48000',
'extra' => ''
],
];
$jsonFile = __DIR__ . '/input.json';
if (file_exists($jsonFile)) {
$raw = file_get_contents($jsonFile);
$data = json_decode($raw, true);
if (!is_array($data)) $data = $defaults;
} else {
$data = $defaults;
}
$use_common_backend = $data['use_common_backend'];
$input_source = $data['input'];
$input_rtmp_mount = $data['rtmp']['mount'];
$jsonFile = __DIR__ . '/output.json';
$defaults = [
'service_display' => 'disable',
'service_rtmp0_multiple' => 'disable',
'service_rtmp0_hls' => 'disable',
'service_rtmp0_dash' => 'disable',
'service_rtmp1_multiple' => 'disable',
'service_rtmp1_hls' => 'disable',
'service_rtmp1_dash' => 'disable',
'service_udp0' => 'disable',
'service_udp1' => 'disable',
'service_udp2' => 'disable',
'service_srt_multiple' => 'disable',
'service_custom' => 'disable',
'rtmp0_multiple' => [],
'rtmp1_multiple' => [],
'srt_multiple' => [],
'rtmp0' => [
'common_backend' => 'enable',
'resolution' => '1920x1080',
'data_rate' => '6M',
'framerate' => '30',
'gop' => '30',
'extra' => '',
'audio_data_rate' => '128k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000'
],
'rtmp1' => [
'common_backend' => 'disable',
'resolution' => '720x576',
'data_rate' => '1.5M',
'framerate' => '25',
'gop' => '25',
'extra' => '',
'audio_data_rate' => '96k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000'
],
'udp0' => [
'common_backend' => 'disable',
'udp' => 'udp://@224.1.1.1:8001',
'format' => 'h264_qsv',
'resolution' => '1280x720',
'data_rate' => '2.2M',
'framerate' => '25',
'gop' => '25',
'extra' => '',
'audio_format' => 'aac',
'audio_data_rate' => '128k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000',
'service_udp0_output' => 'default',
'udp0_service_name' => ''
],
'udp1' => [
'common_backend' => 'disable',
'udp' => 'udp://@224.1.1.1:8001',
'format' => 'h264_qsv',
'resolution' => '720x576',
'data_rate' => '1.5M',
'framerate' => '25',
'gop' => '25',
'extra' => '',
'audio_format' => 'mp2',
'audio_data_rate' => '128k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000',
'service_udp1_output' => 'default',
'udp1_service_name' => ''
],
'udp2' => [
'common_backend' => 'disable',
'udp' => 'udp://@224.1.1.1:8002',
'format' => 'mpeg2video',
'resolution' => '720x576',
'data_rate' => '3M',
'framerate' => '25',
'gop' => '25',
'extra' => '',
'audio_format' => 'mp2',
'audio_data_rate' => '96k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000',
'service_udp2_output' => 'default',
'udp2_service_name' => ''
],
'srt' => [
'common_backend' => 'enable',
'format' => 'mpeg2video',
'resolution' => '1920x1080',
'data_rate' => '6M',
'framerate' => '50',
'gop' => '50',
'extra' => '',
'audio_format' => 'aac',
'audio_data_rate' => '256k',
'audio_db_gain' => '0dB',
'audio_sample_rate' => '48000'
],
'display_resolution' => '720x576',
'display_audio' => '0,3',
'display_hdmi_sdi' => 'disable',
'custom_output' => ''
];
for ($i = 1; $i <= 11; $i++) {
$defaults['rtmp0_multiple'][$i] = ['url' => '', 'name' => '', 'enabled' => false];
$defaults['rtmp1_multiple'][$i] = ['url' => '', 'name' => '', 'enabled' => false];
$defaults['srt_multiple'][$i] = ['url' => '', 'name' => '', 'enabled' => false];
}
if (file_exists($jsonFile)) {
$raw = file_get_contents($jsonFile);
$data = json_decode($raw, true);
if (!is_array($data)) $data = $defaults;
$data = array_replace_recursive($defaults, $data);
} else {
$data = $defaults;
}
$service_rtmp0_hls = $data['service_rtmp0_hls'];
$service_rtmp0_dash = $data['service_rtmp0_dash'];
$service_rtmp1_hls = $data['service_rtmp1_hls'];
$service_rtmp1_dash = $data['service_rtmp1_dash'];
$rtmp0_multiple = $data['rtmp0_multiple'];
$rtmp1_multiple = $data['rtmp1_multiple'];
$srt_multiple = $data['srt_multiple'];
switch ($service) {
case "rtmp":
if ($service_rtmp0_hls === "enable") {
$hls0 = "
hls on;
hls_path /var/www/html/hls/shree;
hls_fragment 6;
hls_playlist_length 48;
hls_continuous on;
";
} else {
$hls0 = "
";
}
if ($service_rtmp0_dash === "enable") {
$dash0 = "
dash on;
dash_path /var/www/html/dash/shree;
dash_fragment 10;
dash_playlist_length 60;
";
} else {
$dash0 = "
";
}
if ($service_rtmp1_hls === "enable") {
$hls1 = "
hls on;
hls_path /var/www/html/hls/shreeshree;
hls_fragment 6;
hls_playlist_length 48;
hls_continuous on;
";
} else {
$hls1 = "
";
}
if ($service_rtmp1_dash === "enable") {
$dash1 = "
dash on;
dash_path /var/www/html/dash/shreeshree;
dash_fragment 10;
dash_playlist_length 60;
";
} else {
$dash1 = "
";
}
$rtmp_push0 = "";
for ($i = 1; $i <= 11; $i++) {
if ($rtmp0_multiple[$i]['enabled'] == 'true') {
$rtmp_push0 .= "
push " . $rtmp0_multiple[$i]['url'] . ";";
}
}
$rtmp_push1 = "";
for ($i = 1; $i <= 11; $i++) {
if ($rtmp1_multiple[$i]['enabled'] == 'true') {
$rtmp_push1 .= "
push " . $rtmp1_multiple[$i]['url'] . ";";
}
}
$nginx = "
user www-data;
worker_processes auto;
worker_rlimit_nofile 100000;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 8192;
multi_accept on;
}
rtmp {
server {
listen 1935;
chunk_size 4096;
";
if ($input_source === "rtmp" || $input_rtmp_mount !== "") {
$nginx .= "
application " . $input_rtmp_mount . " {
live on;
record off;
meta off;
wait_video on;
sync 10ms;
idle_streams off;
}
";
}
$nginx .= "
application shree {
live on;
record off;
meta off;
wait_video on;
sync 10ms;
idle_streams off;
" . $hls0 . "
" . $dash0 . "
" . $rtmp_push0 . "
}
application shreeshree {
live on;
record off;
meta off;
wait_video on;
sync 10ms;
idle_streams off;
" . $hls1 . "
" . $dash1 . "
" . $rtmp_push1 . "
}
}
}";
$nginx .= "
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
";
$file = "/var/www/nginx.conf";
file_put_contents($file, $nginx);
exec('sudo cp /var/www/nginx.conf /etc/nginx/nginx.conf');
exec("sudo nginx -t 2>&1", $output, $status);
if ($status === 0) {
exec("sudo systemctl restart nginx 2>&1", $o, $s);
} else {
exec('sudo cp /var/www/default_nginx.conf /etc/nginx/nginx.conf');
exec("sudo systemctl restart nginx");
}
break;
case "srt":
$srt_push = "";
for ($i = 1; $i <= 11; $i++) {
if ($srt_multiple[$i]['enabled'] == 1) {
$srt_push .= " " . $srt_multiple[$i]['url'];
}
}
$sls = "
srt {
worker_threads 64;
worker_connections 1000;
log_file /tmp/logs/error.log ;
log_level info;
server {
listen 1937;
latency 2000; #ms
domain_player shree;
domain_publisher " . $srt_pass1 . " ;
backlog 100;
idle_streams_timeout 10;
app {
app_player bhatt ;
app_publisher " . $srt_pass2 . " ;
record_hls off;
record_hls_segment_duration 10;
";
if ($srt_push != "")
$sls .= "
relay {
type push;
mode all; #all; hash
reconnect_interval 10;
idle_streams_timeout -1;
upstreams " . $srt_push . " ;
}";
$sls .= "
}
}
}
";
$file = "/var/www/sls.conf";
file_put_contents($file, $sls);
exec('sudo systemctl enable srt');
exec('sudo systemctl restart srt');
break;
}
}