Updating FFmpeg variables and improving request handling in the API

This commit is contained in:
Divarion-D
2026-03-09 00:03:18 +03:00
parent ce30971af1
commit 41b8adeeb3
13 changed files with 55 additions and 38 deletions
+3 -3
View File
@@ -1575,7 +1575,7 @@ $rServers = ServerRepository::getAll(); // 50+ call-sites
| `$rConfig` | `ConfigReader::getAll()` | core + streaming |
| `$rServers` | `ServerRepository::getAll()` | core + streaming |
| `$rFFPROBE` | `FfmpegPaths::probe()` | core + streaming |
| `$rFFMPEG` | `FfmpegPaths::cpu()` | core + streaming |
| `$rFFMPEG_CPU` | `FfmpegPaths::cpu()` | core + streaming |
| `$rFFMPEG_GPU` | `FfmpegPaths::gpu()` | core + streaming |
| `$db` | `DatabaseFactory` | уже глобальная |
@@ -1596,9 +1596,9 @@ public static function probeStream($url) {
**Обновлённые файлы (54 замены в 20 файлах):**
- `core/Init/LegacyInitializer.php` — добавлен `exportGlobals()`, вызов из `initCore()` + FFmpeg globals в `initStreaming()`
- `streaming/Codec/FFprobeRunner.php` — `global $rSettings, $rFFPROBE`
- `streaming/Codec/SubtitleExtractor.php` — `global $rSettings, $rFFMPEG`
- `streaming/Codec/SubtitleExtractor.php` — `global $rSettings, $rFFMPEG_CPU`
- `streaming/Health/ProcessChecker.php` — `global $rServers`
- `domain/Stream/StreamProcess.php` — 4 метода: `global $db, $rSettings, $rServers, $rFFMPEG, $rFFMPEG_GPU`; переименование `$rFFMPEGCPU`→`$rFFMPEG`, `$rFFMPEGGPU`→`$rFFMPEG_GPU`
- `domain/Stream/StreamProcess.php` — 4 метода: `global $db, $rSettings, $rServers, $rFFMPEG_CPU, $rFFMPEG_GPU`; переименование `$rFFMPEGCPU`→`$rFFMPEG_CPU`, `$rFFMPEGGPU`→`$rFFMPEG_GPU`
- `domain/Stream/ConnectionTracker.php` — 5 методов: `global $rSettings, $rServers, $db`
- `domain/Stream/PlaylistGenerator.php` — `global $db, $rSettings, $rServers`
- `domain/Stream/StreamService.php` — `global $db, $rSettings`
+3 -3
View File
@@ -4491,9 +4491,9 @@ if (isset($_SESSION['hash'])) {
}
if (RequestManager::getAll()['action'] != 'multi') {
}
$rType = RequestManager::getAll()['type'];
$rRequestIDs = json_decode(RequestManager::getAll()['ids'], true);
$rSub = RequestManager::getAll()['sub'];
$rType = RequestManager::getAll()['type'] ?? '';
$rRequestIDs = json_decode(RequestManager::getAll()['ids'] ?? '[]', true) ?: [];
$rSub = RequestManager::getAll()['sub'] ?? '';
if (count($rRequestIDs) != 0) {
switch ($rType) {
+1 -1
View File
@@ -8,7 +8,7 @@ if (!isset($__viewMode)):
goHome();
}
$rAvailableServers = $rServers = array();
$rAvailableServers = array();
$rStream = $rProgramme = null;
if (isset(RequestManager::getAll()['id'])) {
+3 -3
View File
@@ -104,7 +104,7 @@ class LegacyInitializer {
// FFmpeg paths — export to globals (streaming context)
$GLOBALS['rFFPROBE'] = FfmpegPaths::probe();
$GLOBALS['rFFMPEG'] = FfmpegPaths::cpu();
$GLOBALS['rFFMPEG_CPU'] = FfmpegPaths::cpu();
$GLOBALS['rFFMPEG_GPU'] = FfmpegPaths::gpu();
self::syncStreamingContainer();
@@ -125,7 +125,7 @@ class LegacyInitializer {
* $rConfig — config.ini данные (ConfigReader)
* $rServers — все серверы (ServerRepository)
* $rFFPROBE — путь к ffprobe (FfmpegPaths)
* $rFFMPEG — путь к ffmpeg CPU (FfmpegPaths)
* $rFFMPEG_CPU — путь к ffmpeg CPU (FfmpegPaths)
* $rFFMPEG_GPU — путь к ffmpeg GPU (FfmpegPaths)
*/
public static function exportGlobals(): void {
@@ -134,7 +134,7 @@ class LegacyInitializer {
$GLOBALS['rConfig'] = ConfigReader::getAll();
$GLOBALS['rServers'] = ServerRepository::getAll();
$GLOBALS['rFFPROBE'] = FfmpegPaths::probe();
$GLOBALS['rFFMPEG'] = FfmpegPaths::cpu();
$GLOBALS['rFFMPEG_CPU'] = FfmpegPaths::cpu();
$GLOBALS['rFFMPEG_GPU'] = FfmpegPaths::gpu();
}
+4
View File
@@ -282,6 +282,10 @@ class ProcessManager {
}
// Write our PID
$lockDir = dirname($lockFile);
if (!is_dir($lockDir)) {
@mkdir($lockDir, 0775, true);
}
file_put_contents($lockFile, getmypid());
return true;
+2 -2
View File
@@ -209,8 +209,8 @@ function loadCron() {
}
if (!SettingsManager::getAll()['kill_rogue_ffmpeg']) {
} else {
exec("ps aux | grep -v grep | grep '/*_.m3u8' | awk '{print \$2}'", $rFFMPEG);
foreach ($rFFMPEG as $rPID) {
exec("ps aux | grep -v grep | grep '/*_.m3u8' | awk '{print \$2}'", $rRoguePIDs);
foreach ($rRoguePIDs as $rPID) {
if (!(is_numeric($rPID) && 0 < intval($rPID)) || in_array($rPID, $rActivePIDs)) {
} else {
echo 'Kill Roque PID: ' . $rPID . "\n";
+4
View File
@@ -8,6 +8,10 @@ if (posix_getpwuid(posix_geteuid())['name'] == 'xc_vm') {
$rIdentifier = CRONS_TMP_PATH . md5(Encryption::generateUniqueCode(SettingsManager::getAll()['live_streaming_pass']) . __FILE__);
ProcessManager::acquireCronLock($rIdentifier);
foreach (array(TMP_PATH, CRONS_TMP_PATH, DIVERGENCE_TMP_PATH, FLOOD_TMP_PATH, MINISTRA_TMP_PATH, SIGNALS_TMP_PATH, LOGS_TMP_PATH) as $rTmpPath) {
if (!is_dir($rTmpPath)) {
@mkdir($rTmpPath, 0775, true);
continue;
}
foreach (scandir($rTmpPath) as $rFile) {
$fullPath = $rTmpPath . '/' . $rFile;
+3
View File
@@ -3,6 +3,9 @@
class ServerRepository {
public static function getAll($rForce = false) {
global $db, $rSettings;
if (!$rSettings) {
$rSettings = SettingsManager::getAll();
}
if (!$rForce) {
$rCache = FileCache::getCache('servers', 10);
if (!empty($rCache)) {
+10 -10
View File
@@ -95,7 +95,7 @@ class StreamProcess {
}
public static function createChannelItem($rStreamID, $rSource) {
global $db, $rSettings, $rServers, $rFFMPEG, $rFFMPEG_GPU;
global $db, $rSettings, $rServers, $rFFMPEG_CPU, $rFFMPEG_GPU;
$rStream = array();
$rLoopback = false;
$db->query('SELECT * FROM `streams` t1 INNER JOIN `streams_types` t2 ON t2.type_id = t1.type AND t1.type = 3 LEFT JOIN `profiles` t4 ON t1.transcode_profile_id = t4.profile_id WHERE t1.direct_source = 0 AND t1.id = ?', $rStreamID);
@@ -170,7 +170,7 @@ class StreamProcess {
}
}
$rCommand = ((isset($rStream['stream_info']['transcode_attributes']['gpu']) ? $rFFMPEG_GPU : $rFFMPEG)) . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err {GPU} -fflags +genpts -async 1 -i {STREAM_SOURCE} {LOGO} ';
$rCommand = ((isset($rStream['stream_info']['transcode_attributes']['gpu']) ? $rFFMPEG_GPU : $rFFMPEG_CPU)) . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err {GPU} -fflags +genpts -async 1 -i {STREAM_SOURCE} {LOGO} ';
if (!array_key_exists('-acodec', $rStream['stream_info']['transcode_attributes'])) {
$rStream['stream_info']['transcode_attributes']['-acodec'] = 'copy';
@@ -300,7 +300,7 @@ class StreamProcess {
}
public static function startMovie($rStreamID) {
global $db, $rSettings, $rServers, $rFFMPEG, $rFFMPEG_GPU;
global $db, $rSettings, $rServers, $rFFMPEG_CPU, $rFFMPEG_GPU;
$rStream = array();
$rLoopback = false;
$db->query('SELECT * FROM `streams` t1 INNER JOIN `streams_types` t2 ON t2.type_id = t1.type AND t2.live = 0 LEFT JOIN `profiles` t4 ON t1.transcode_profile_id = t4.profile_id WHERE t1.direct_source = 0 AND t1.id = ?', $rStreamID);
@@ -403,7 +403,7 @@ class StreamProcess {
$rInputCodec = '-c:v ' . $rFFProbeOutput['codecs']['video']['codec_name'] . '_cuvid';
}
}
$rFFMPEG = ((isset($rStream['stream_info']['transcode_attributes']['gpu']) ? $rFFMPEG_GPU : $rFFMPEG)) . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err {GPU} {FETCH_OPTIONS} -fflags +genpts -async 1 {READ_NATIVE} -i {STREAM_SOURCE} {LOGO} ' . $rSubtitlesImport;
$rFFMPEG = ((isset($rStream['stream_info']['transcode_attributes']['gpu']) ? $rFFMPEG_GPU : $rFFMPEG_CPU)) . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err {GPU} {FETCH_OPTIONS} -fflags +genpts -async 1 {READ_NATIVE} -i {STREAM_SOURCE} {LOGO} ' . $rSubtitlesImport;
$rMap = '-map 0 -copy_unknown ';
if (!empty($rStream['stream_info']['custom_map'])) {
$rMap = escapeshellcmd($rStream['stream_info']['custom_map']) . ' -copy_unknown ';
@@ -506,7 +506,7 @@ class StreamProcess {
}
public static function startStream($rStreamID, $rFromCache = false, $rForceSource = null, $rLLOD = false, $rStartPos = 0) {
global $db, $rSettings, $rServers, $rFFMPEG, $rFFMPEG_GPU, $rFFPROBE;
global $db, $rSettings, $rServers, $rFFMPEG_CPU, $rFFMPEG_GPU, $rFFPROBE;
$rSegmentSettings = array('seg_time' => intval($rSettings['seg_time']), 'seg_list_size' => intval($rSettings['seg_list_size']), 'seg_delete_threshold' => intval($rSettings['seg_delete_threshold']));
if (file_exists(STREAMS_PATH . $rStreamID . '_.pid')) {
unlink(STREAMS_PATH . $rStreamID . '_.pid');
@@ -534,7 +534,7 @@ class StreamProcess {
$rTimeout = intval($rAnalyseDuration / 1000000) + $rSettings['probe_extra_wait'];
$rFFProbee = 'timeout ' . $rTimeout . ' ' . $rFFPROBE . ' {FETCH_OPTIONS} -probesize ' . $rProbesize . ' -analyzeduration ' . $rAnalyseDuration . ' {CONCAT} -i {STREAM_SOURCE} -v quiet -print_format json -show_streams -show_format';
$rFetchOptions = array();
$rFetchOptions = '';
$rLoopback = false;
$rOffset = 0;
@@ -789,11 +789,11 @@ class StreamProcess {
$rGenPTS = '-fflags +genpts -async 1';
} else {
if (is_array($rFFProbeOutput) && isset($rFFProbeOutput['codecs']['audio']['codec_name']) && in_array($rFFProbeOutput['codecs']['audio']['codec_name'], array('ac3', 'eac3')) && $rSettings['dts_legacy_ffmpeg']) {
$rFFMPEG = FFMPEG_BIN_40;
$rFFMPEG_CPU = FFMPEG_BIN_40;
$rFFPROBE = FFPROBE_BIN_40;
}
$rNoFix = ($rFFMPEG == FFMPEG_BIN_40 ? '-nofix_dts' : '');
$rNoFix = ($rFFMPEG_CPU == FFMPEG_BIN_40 ? '-nofix_dts' : '');
$rGenPTS = $rNoFix . ' -start_at_zero -copyts -vsync 0 -correct_ts_overflow 0 -avoid_negative_ts disabled -max_interleave_delta 0';
}
@@ -814,7 +814,7 @@ class StreamProcess {
$rStream['stream_info']['transcode_attributes'] = array();
}
$rFFMPEG = ((isset($rStream['stream_info']['transcode_attributes']['gpu']) ? $rFFMPEG_GPU : $rFFMPEG)) . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err ' . $rOptions . ' {GEN_PTS} {READ_NATIVE} -probesize ' . $rProbesize . ' -analyzeduration ' . $rAnalyseDuration . ' -progress "' . $rProgressURL . '" {CONCAT} -i {STREAM_SOURCE} {LOGO} ';
$rFFMPEG = ((isset($rStream['stream_info']['transcode_attributes']['gpu']) ? $rFFMPEG_GPU : $rFFMPEG_CPU)) . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err ' . $rOptions . ' {GEN_PTS} {READ_NATIVE} -probesize ' . $rProbesize . ' -analyzeduration ' . $rAnalyseDuration . ' -progress "' . $rProgressURL . '" {CONCAT} -i {STREAM_SOURCE} {LOGO} ';
if (!array_key_exists('-acodec', $rStream['stream_info']['transcode_attributes'])) {
$rStream['stream_info']['transcode_attributes']['-acodec'] = 'copy';
@@ -829,7 +829,7 @@ class StreamProcess {
}
} else {
$rStream['stream_info']['transcode_attributes'] = array();
$rFFMPEG = ((stripos($rStream['stream_info']['custom_ffmpeg'], 'nvenc') !== false ? $rFFMPEG_GPU : $rFFMPEG)) . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -progress "' . $rProgressURL . '" ' . $rStream['stream_info']['custom_ffmpeg'];
$rFFMPEG = ((stripos($rStream['stream_info']['custom_ffmpeg'], 'nvenc') !== false ? $rFFMPEG_GPU : $rFFMPEG_CPU)) . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -progress "' . $rProgressURL . '" ' . $rStream['stream_info']['custom_ffmpeg'];
}
$rLLODOptions = ($rLLOD && !$rLoopback ? '-fflags nobuffer -flags low_delay -strict experimental' : '');
+2 -2
View File
@@ -105,8 +105,8 @@ if (ProcessManager::isStreamRunning($rPID, $rStreamID)) {
}
if (SettingsManager::getAll()['kill_rogue_ffmpeg']) {
exec('ps aux | grep -v grep | grep \'/' . $rStreamID . '_.m3u8\' | awk \'{print $2}\'', $rFFMPEG);
foreach ($rFFMPEG as $rRoguePID) {
exec('ps aux | grep -v grep | grep \'/' . $rStreamID . '_.m3u8\' | awk \'{print $2}\'', $rRoguePIDs);
foreach ($rRoguePIDs as $rRoguePID) {
if (is_numeric($rRoguePID) && intval($rRoguePID) > 0 && intval($rRoguePID) != intval($rPID)) {
shell_exec('kill -9 ' . $rRoguePID . ';');
}
+6
View File
@@ -143,6 +143,12 @@ final class Logger {
'env' => php_sapi_name() // SAPI name (cli, fpm-fcgi, etc.)
];
// Ensure log directory exists
$logDir = dirname(self::$logFile);
if (!is_dir($logDir)) {
@mkdir($logDir, 0775, true);
}
// Write to file as base64-encoded JSON (easy to parse and prevents line corruption)
file_put_contents(
self::$logFile,
+2 -2
View File
@@ -2,9 +2,9 @@
class SubtitleExtractor {
public static function extractSubtitle($rStreamID, $rSourceURL, $rIndex) {
global $rSettings, $rFFMPEG;
global $rSettings, $rFFMPEG_CPU;
$rTimeout = 10;
$rCommand = 'timeout ' . $rTimeout . ' ' . $rFFMPEG . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err -i "' . $rSourceURL . '" -map 0:s:' . intval($rIndex) . ' ' . VOD_PATH . intval($rStreamID) . '_' . intval($rIndex) . '.srt';
$rCommand = 'timeout ' . $rTimeout . ' ' . $rFFMPEG_CPU . ' -y -nostdin -hide_banner -loglevel ' . (($rSettings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err -i "' . $rSourceURL . '" -map 0:s:' . intval($rIndex) . ' ' . VOD_PATH . intval($rStreamID) . '_' . intval($rIndex) . '.srt';
exec($rCommand, $rOutput);
if (file_exists(VOD_PATH . intval($rStreamID) . '_' . intval($rIndex) . '.srt')) {
if (filesize(VOD_PATH . intval($rStreamID) . '_' . intval($rIndex) . '.srt') != 0) {
+12 -12
View File
@@ -42,10 +42,10 @@ switch ($rAction) {
case 'start':
$rStreamIDs = array_map('intval', RequestManager::getAll()['stream_ids']);
$rForce = (RequestManager::getAll()['force'] ?: false);
$rServers = (empty(RequestManager::getAll()['servers']) ? array_keys($rAllServers) : array_map('intval', RequestManager::getAll()['servers']));
$rServerIDs = (empty(RequestManager::getAll()['servers']) ? array_keys($rAllServers) : array_map('intval', RequestManager::getAll()['servers']));
$rURLs = array();
foreach ($rServers as $rServerID) {
foreach ($rServerIDs as $rServerID) {
$rURLs[$rServerID] = array('url' => $rAllServers[$rServerID]['api_url_ip'] . '&action=vod', 'postdata' => array('function' => $rSubAction, 'stream_ids' => $rStreamIDs, 'force' => $rForce));
}
CurlClient::getMultiCURL($rURLs);
@@ -55,10 +55,10 @@ switch ($rAction) {
case 'stop':
$rStreamIDs = array_map('intval', RequestManager::getAll()['stream_ids']);
$rServers = (empty(RequestManager::getAll()['servers']) ? array_keys($rAllServers) : array_map('intval', RequestManager::getAll()['servers']));
$rServerIDs = (empty(RequestManager::getAll()['servers']) ? array_keys($rAllServers) : array_map('intval', RequestManager::getAll()['servers']));
$rURLs = array();
foreach ($rServers as $rServerID) {
foreach ($rServerIDs as $rServerID) {
$rURLs[$rServerID] = array('url' => $rAllServers[$rServerID]['api_url_ip'] . '&action=vod', 'postdata' => array('function' => $rSubAction, 'stream_ids' => $rStreamIDs));
}
CurlClient::getMultiCURL($rURLs);
@@ -73,10 +73,10 @@ switch ($rAction) {
switch ($rSubAction) {
case 'start':
$rStreamIDs = array_map('intval', RequestManager::getAll()['stream_ids']);
$rServers = (empty(RequestManager::getAll()['servers']) ? array_keys($rAllServers) : array_map('intval', RequestManager::getAll()['servers']));
$rServerIDs = (empty(RequestManager::getAll()['servers']) ? array_keys($rAllServers) : array_map('intval', RequestManager::getAll()['servers']));
$rURLs = array();
foreach ($rServers as $rServerID) {
foreach ($rServerIDs as $rServerID) {
$rURLs[$rServerID] = array('url' => $rAllServers[$rServerID]['api_url_ip'] . '&action=stream', 'postdata' => array('function' => $rSubAction, 'stream_ids' => $rStreamIDs));
}
CurlClient::getMultiCURL($rURLs);
@@ -86,10 +86,10 @@ switch ($rAction) {
case 'stop':
$rStreamIDs = array_map('intval', RequestManager::getAll()['stream_ids']);
$rServers = (empty(RequestManager::getAll()['servers']) ? array_keys($rAllServers) : array_map('intval', RequestManager::getAll()['servers']));
$rServerIDs = (empty(RequestManager::getAll()['servers']) ? array_keys($rAllServers) : array_map('intval', RequestManager::getAll()['servers']));
$rURLs = array();
foreach ($rServers as $rServerID) {
foreach ($rServerIDs as $rServerID) {
$rURLs[$rServerID] = array('url' => $rAllServers[$rServerID]['api_url_ip'] . '&action=stream', 'postdata' => array('function' => $rSubAction, 'stream_ids' => $rStreamIDs));
}
CurlClient::getMultiCURL($rURLs);
@@ -113,8 +113,8 @@ switch ($rAction) {
$rStreams = $db->get_rows(true, 'stream_id', false, 'server_id');
$rOutput = array();
foreach ($rStreams as $rStreamID => $rServers) {
$rOutput[$rStreamID] = array_keys($rServers);
foreach ($rStreams as $rStreamID => $rStreamServers) {
$rOutput[$rStreamID] = array_keys($rStreamServers);
}
echo json_encode($rOutput);
@@ -125,8 +125,8 @@ switch ($rAction) {
$rStreams = $db->get_rows(true, 'stream_id', false, 'server_id');
$rOutput = array();
foreach ($rStreams as $rStreamID => $rServers) {
$rOutput[$rStreamID] = array_keys($rServers);
foreach ($rStreams as $rStreamID => $rStreamServers) {
$rOutput[$rStreamID] = array_keys($rStreamServers);
}
echo json_encode($rOutput);