diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 303ffa7f..00000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -bin/ffmpeg filter=lfs diff=lfs merge=lfs -text -bin/ffprobe filter=lfs diff=lfs merge=lfs -text diff --git a/admin/api.php b/admin/api.php index 9c7a5043..937e5fc7 100644 --- a/admin/api.php +++ b/admin/api.php @@ -1274,10 +1274,10 @@ shell_exec(PHP_BIN . ' ' . CRON_PATH . 'cache_engine.php'); - // $rCache = intval(trim(shell_exec('pgrep -U xui | xargs ps -f -p | grep cache_handler | grep -v grep | grep -v pgrep | wc -l'))); - // if ($rCache == 0) { - // shell_exec(PHP_BIN . ' ' . TOOL_PATH . 'cache_handler.php > /dev/null 2>/dev/null &'); - // } + $rCache = intval(trim(shell_exec('pgrep -U xtreamcodes | xargs ps -f -p | grep cache_handler | grep -v grep | grep -v pgrep | wc -l'))); + if ($rCache == 0) { + shell_exec(PHP_BIN . ' ' . TOOLS_PATH . 'cache_handler.php > /dev/null 2>/dev/null &'); + } echo json_encode(array('result' => true)); diff --git a/admin/functions.php b/admin/functions.php index db75cd0f..11155cd5 100644 --- a/admin/functions.php +++ b/admin/functions.php @@ -271,6 +271,7 @@ function setSettings(array $settings) { define('USER_TMP_PATH', CACHE_TMP_PATH . 'users/'); define('SERIES_TMP_PATH', CACHE_TMP_PATH . 'series/'); define('PHP_BIN', '/home/xtreamcodes/bin/php/bin/php'); +define('TOOLS_PATH', MAIN_DIR . 'tools/'); require_once realpath(dirname(__FILE__)) . "/mobiledetect.php"; require_once realpath(dirname(__FILE__)) . "/gauth.php"; diff --git a/bin/ffmpeg b/bin/ffmpeg deleted file mode 100644 index c9c8590d..00000000 --- a/bin/ffmpeg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cb889edc4110d4373624fd97af17dbc179060c8c284e9107af3411dbc85e174c -size 119570168 diff --git a/bin/ffmpeg_bin/4.0/ffmpeg b/bin/ffmpeg_bin/4.0/ffmpeg new file mode 100644 index 00000000..992bbba7 Binary files /dev/null and b/bin/ffmpeg_bin/4.0/ffmpeg differ diff --git a/bin/ffmpeg_bin/4.0/ffprobe b/bin/ffmpeg_bin/4.0/ffprobe new file mode 100644 index 00000000..64f4e8aa Binary files /dev/null and b/bin/ffmpeg_bin/4.0/ffprobe differ diff --git a/bin/ffmpeg_bin/4.3/ffmpeg b/bin/ffmpeg_bin/4.3/ffmpeg new file mode 100644 index 00000000..13b2439e Binary files /dev/null and b/bin/ffmpeg_bin/4.3/ffmpeg differ diff --git a/bin/ffmpeg_bin/4.3/ffprobe b/bin/ffmpeg_bin/4.3/ffprobe new file mode 100644 index 00000000..5fce4ae0 Binary files /dev/null and b/bin/ffmpeg_bin/4.3/ffprobe differ diff --git a/bin/ffmpeg_bin/4.4/ffmpeg b/bin/ffmpeg_bin/4.4/ffmpeg new file mode 100644 index 00000000..97591b47 Binary files /dev/null and b/bin/ffmpeg_bin/4.4/ffmpeg differ diff --git a/bin/ffmpeg_bin/4.4/ffprobe b/bin/ffmpeg_bin/4.4/ffprobe new file mode 100644 index 00000000..1583858d Binary files /dev/null and b/bin/ffmpeg_bin/4.4/ffprobe differ diff --git a/bin/ffprobe b/bin/ffprobe deleted file mode 100644 index 0a992012..00000000 --- a/bin/ffprobe +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4a059de007b2038fdd4b75345f7f1b01a3420fd2de8ae1c2039f11bf54d99e73 -size 119447832 diff --git a/crons/vod.php b/crons/vod.php index 718cbfb9..f18ed6a2 100644 --- a/crons/vod.php +++ b/crons/vod.php @@ -34,7 +34,7 @@ function loadCron() { } } } - $pid = ipTV_servers::getPidFromProcessName(SERVER_ID, FFMPEG_PATH); + $pid = ipTV_servers::getPidFromProcessName(SERVER_ID, ipTV_lib::$FFMPEG_CPU); $ipTV_db->query("SELECT t1.*,t2.* FROM `streams_servers` t1 INNER JOIN `streams` t2 ON t2.id = t1.stream_id AND t2.direct_source = 0 INNER JOIN `streams_types` t3 ON t3.type_id = t2.type AND t3.live = 0 WHERE (t1.to_analyze = 1 OR t1.stream_status = 2) AND t1.server_id = '%d'", SERVER_ID); if (0 < $ipTV_db->num_rows()) { $series_data = $ipTV_db->get_rows(); diff --git a/database.sql b/database.sql index ae748756..8b49e650 100644 --- a/database.sql +++ b/database.sql @@ -1119,7 +1119,7 @@ INSERT INTO `settings` (`id`, `name`, `value`) VALUES ('160', 'kill_rogue_ffmpeg', '1'), ('161', 'segment_type', '1'), ('162', 'vod_limit_perc', '150'), -('163', 'enable_cache', '1'), +('163', 'enable_cache', '0'), ('164', 'last_cache', '0'), ('165', 'last_cache_taken', '0'), ('166', 'cache_thread_count', '4'), @@ -1131,7 +1131,14 @@ INSERT INTO `settings` (`id`, `name`, `value`) VALUES ('172', 'block_streaming_servers', '0'), ('173', 'block_proxies', '0'), ('174', 'ignore_invalid_users', '0'), -('175', 'disable_mag_token', '0'); +('175', 'disable_mag_token', '0'), +('176', 'ffmpeg_cpu', ''), +('177', 'dts_legacy_ffmpeg', '0'), +('178', 'read_native_hls', '1'), +('179', 'player_allow_hevc', '0'), +('180', 'bruteforce_mac_attempts', '5'), +('181', 'bruteforce_username_attempts', '10'), +('182', 'bruteforce_frequency', '300'); -- -------------------------------------------------------- @@ -1358,22 +1365,31 @@ CREATE TABLE IF NOT EXISTS `streams_seasons` ( CREATE TABLE IF NOT EXISTS `streams_servers` ( `server_stream_id` int(11) NOT NULL AUTO_INCREMENT, - `stream_id` int(11) NOT NULL, - `server_id` int(11) NOT NULL, + `stream_id` int(11) DEFAULT NULL, + `server_id` int(11) DEFAULT NULL, `parent_id` int(11) DEFAULT NULL, `pid` int(11) DEFAULT NULL, - `to_analyze` tinyint(4) NOT NULL DEFAULT 0, - `stream_status` int(11) NOT NULL DEFAULT 0, + `to_analyze` tinyint(4) DEFAULT '0', + `stream_status` int(11) DEFAULT '0', `stream_started` int(11) DEFAULT NULL, - `stream_info` mediumtext NOT NULL, + `stream_info` mediumtext COLLATE utf8_unicode_ci, `monitor_pid` int(11) DEFAULT NULL, - `current_source` mediumtext DEFAULT NULL, + `aes_pid` int(11) DEFAULT NULL, + `current_source` mediumtext COLLATE utf8_unicode_ci, `bitrate` int(11) DEFAULT NULL, - `progress_info` text NOT NULL, - `on_demand` tinyint(4) NOT NULL DEFAULT 0, + `progress_info` mediumtext COLLATE utf8_unicode_ci, + `cc_info` mediumtext COLLATE utf8_unicode_ci, + `on_demand` tinyint(4) DEFAULT '0', `delay_pid` int(11) DEFAULT NULL, `delay_available_at` int(11) DEFAULT NULL, + `pids_create_channel` mediumtext COLLATE utf8_unicode_ci, + `cchannel_rsources` mediumtext COLLATE utf8_unicode_ci, `updated` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `compatible` tinyint(1) DEFAULT '0', + `audio_codec` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, + `video_codec` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, + `resolution` int(5) DEFAULT NULL, + `ondemand_check` int(16) DEFAULT NULL, PRIMARY KEY (`server_stream_id`), UNIQUE KEY `stream_id_2` (`stream_id`,`server_id`), KEY `stream_id` (`stream_id`), diff --git a/permissions.sh b/permissions.sh index a2a0db26..303b87c5 100644 --- a/permissions.sh +++ b/permissions.sh @@ -1,5 +1,6 @@ sudo find /home/xtreamcodes/ -type d -exec chmod 755 {} \; sudo find /home/xtreamcodes/ -type f -exec chmod 550 {} \; +sudo find /home/xtreamcodes/bin/ffmpeg_bin -type f -exec chmod 551 {} \; chmod 0750 /home/xtreamcodes/bin chmod 0750 /home/xtreamcodes/config @@ -11,9 +12,6 @@ chmod 0750 /home/xtreamcodes/signals # chmod 0550 /home/xtreamcodes/bin/nginx_rtmp # chmod 0550 /home/xtreamcodes/bin/php chmod 0771 /home/xtreamcodes/bin/daemons.sh -chmod 0551 /home/xtreamcodes/bin/ffmpeg -chmod 0551 /home/xtreamcodes/bin/ffprobe - chmod 0660 /home/xtreamcodes/bin/php/sockets/* # chmod 0644 /home/xtreamcodes/database.sql diff --git a/wwwdir/constants.php b/wwwdir/constants.php index b7376e44..256cb80b 100644 --- a/wwwdir/constants.php +++ b/wwwdir/constants.php @@ -72,12 +72,16 @@ // BINARIES FILE define('PHP_BIN', '/home/xtreamcodes/bin/php/bin/php'); -define('FFMPEG_PATH', file_exists(BIN_PATH . 'ffmpeg') ? BIN_PATH . 'ffmpeg' : '/usr/bin/ffmpeg'); -define('FFPROBE_PATH', file_exists(BIN_PATH . 'ffprobe') ? BIN_PATH . 'ffprobe' : '/usr/bin/ffprobe'); define('YOUTUBE_PATH', BIN_PATH . 'yt-dlp'); define('GEOIP2COUNTRY_FILENAME', BIN_PATH . 'maxmind/GeoLite2-Country.mmdb'); define('GEOIP2ASN_FILENAME', BIN_PATH . 'maxmind/GeoLite2-ASN.mmdb'); define('GEOIP2CITY_FILENAME', BIN_PATH . 'maxmind/GeoLite2-City.mmdb'); +define('FFMPEG_BIN_40', BIN_PATH . 'ffmpeg_bin/4.0/ffmpeg'); +define('FFMPEG_BIN_43', BIN_PATH . 'ffmpeg_bin/4.3/ffmpeg'); +define('FFMPEG_BIN_44', BIN_PATH . 'ffmpeg_bin/4.4/ffmpeg'); +define('FFPROBE_BIN_40', BIN_PATH . 'ffmpeg_bin/4.0/ffprobe'); +define('FFPROBE_BIN_43', BIN_PATH . 'ffmpeg_bin/4.3/ffprobe'); +define('FFPROBE_BIN_44', BIN_PATH . 'ffmpeg_bin/4.4/ffprobe'); // ------------------- // TEMP FOLDERS diff --git a/wwwdir/includes/lib.php b/wwwdir/includes/lib.php index 3c33efbd..8c80ddff 100644 --- a/wwwdir/includes/lib.php +++ b/wwwdir/includes/lib.php @@ -12,6 +12,9 @@ class ipTV_lib { public static $blockedIPs = array(); public static $categories = array(); public static $allowedIPs = array(); + public static $FFMPEG_CPU = null; + public static $FFMPEG_GPU = null; + public static $FFPROBE = null; public static $cached = null; public static function init() { @@ -35,6 +38,21 @@ public static function init() { self::$settings = self::getSettings(); self::$cached = self::$settings["enable_cache"]; date_default_timezone_set(self::$settings["default_timezone"]); + switch (self::$settings['ffmpeg_cpu']) { + case '4.4': + self::$FFMPEG_CPU = FFMPEG_BIN_44; + self::$FFPROBE = FFPROBE_BIN_44; + break; + case '4.3': + self::$FFMPEG_CPU = FFMPEG_BIN_43; + self::$FFPROBE = FFPROBE_BIN_43; + break; + default: + self::$FFMPEG_CPU = FFMPEG_BIN_40; + self::$FFPROBE = FFPROBE_BIN_40; + break; + } + self::$FFMPEG_GPU = FFMPEG_BIN_40; self::$StreamingServers = self::getServers(); self::$blockedISP = self::getBlockedISP(); self::$blockedIPs = self::getBlockedIPs(); @@ -69,9 +87,10 @@ public static function getDiffTimezone($rTimezone) { public static function calculateSegNumbers() { $segments_settings = array(); - $segments_settings['seg_type'] = self::$settings["seg_type"]; + $segments_settings['seg_type'] = self::$settings["segment_type"]; $segments_settings["seg_time"] = intval(self::$settings["seg_time"]); $segments_settings["seg_list_size"] = intval(self::$settings["seg_list_size"]); + $segments_settings["seg_delete_threshold"] = intval(self::$settings["seg_delete_threshold"]); return $segments_settings; } public static function GetIspAddon($rForce = false) { diff --git a/wwwdir/includes/stream.php b/wwwdir/includes/stream.php index 61eb58c5..bf00bb15 100644 --- a/wwwdir/includes/stream.php +++ b/wwwdir/includes/stream.php @@ -2,23 +2,6 @@ class ipTV_stream { public static $ipTV_db; - /** - * Deletes files based on the provided sources. - * - * This function takes an array of file sources and deletes the corresponding files from the STREAMS_PATH directory if they exist. - * - * @param array $sources An array of file sources to be deleted. - * @return void - */ - static function deleteCache($sources) { - if (!empty($sources)) { - foreach ($sources as $source) { - ipTV_lib::unlink_file(STREAMS_PATH . md5($source)); - } - } else { - return null; - } - } /** * Transcodes and builds a stream based on the provided stream ID. * @@ -44,7 +27,7 @@ static function TranscodeBuild($streamID) { } // Construct FFmpeg command - $ffmpegCommand = FFMPEG_PATH . ' -fflags +genpts -async 1 -y -nostdin -hide_banner -loglevel quiet -i "{INPUT}" '; + $ffmpegCommand = ipTV_lib::$FFMPEG_CPU . ' -fflags +genpts -async 1 -y -nostdin -hide_banner -loglevel quiet -i "{INPUT}" '; $ffmpegCommand .= implode(' ', self::parseTranscode($stream['transcode_attributes'])) . ' '; $ffmpegCommand .= '-strict -2 -mpegts_flags +initial_discontinuity -f mpegts "' . CREATED_CHANNELS . $streamID . '_{INPUT_MD5}.ts" >/dev/null 2>/dev/null & jobs -p'; @@ -66,7 +49,7 @@ static function TranscodeBuild($streamID) { return 1; } else if (!empty($stream['pids_create_channel'])) { foreach ($stream['pids_create_channel'] as $key => $pid) { - if (!ipTV_servers::PidsChannels($stream['created_channel_location'], $pid, FFMPEG_PATH)) { + if (!ipTV_servers::PidsChannels($stream['created_channel_location'], $pid, ipTV_lib::$FFMPEG_CPU)) { unset($stream['pids_create_channel'][$key]); } } @@ -76,11 +59,11 @@ static function TranscodeBuild($streamID) { return 2; } - public static function probeStream($rSourceURL, $rFetchArguments = array(), $rPrepend = '', $rParse = true) { + public static function c($rSourceURL, $rFetchArguments = array(), $rPrepend = '', $rParse = true) { $rAnalyseDuration = abs(intval(ipTV_lib::$settings['stream_max_analyze'])); $rProbesize = abs(intval(ipTV_lib::$settings['probesize'])); $rTimeout = intval($rAnalyseDuration / 1000000) + ipTV_lib::$settings['probe_extra_wait']; - $rCommand = $rPrepend . 'timeout ' . $rTimeout . ' ' . FFPROBE_PATH . ' -probesize ' . $rProbesize . ' -analyzeduration ' . $rAnalyseDuration . ' ' . implode(' ', $rFetchArguments) . ' -i "' . $rSourceURL . '" -v quiet -print_format json -show_streams -show_format'; + $rCommand = $rPrepend . 'timeout ' . $rTimeout . ' ' . ipTV_lib::$FFPROBE . ' -probesize ' . $rProbesize . ' -analyzeduration ' . $rAnalyseDuration . ' ' . implode(' ', $rFetchArguments) . ' -i "' . $rSourceURL . '" -v quiet -print_format json -show_streams -show_format'; exec($rCommand, $rReturn); $result = implode("\n", $rReturn); if ($rParse) { @@ -200,7 +183,7 @@ static function startVODstream($streamID) { } $rLogoOptions = (isset($stream['stream_info']['transcode_attributes'][16]) ? $stream['stream_info']['transcode_attributes'][16]['cmd'] : ''); $rInputCodec = ''; - $rFFMPEG = FFMPEG_PATH . ' -y -nostdin -hide_banner -loglevel warning -err_detect ignore_err {FETCH_OPTIONS} -fflags +genpts -async 1 {READ_NATIVE} -i {STREAM_SOURCE} {LOGO} ' . $subtitlesImport; + $rFFMPEG = ipTV_lib::$FFMPEG_CPU . ' -y -nostdin -hide_banner -loglevel warning -err_detect ignore_err {FETCH_OPTIONS} -fflags +genpts -async 1 {READ_NATIVE} -i {STREAM_SOURCE} {LOGO} ' . $subtitlesImport; $map = '-map 0 -copy_unknown '; if (!empty($stream['stream_info']['custom_map'])) { $map = escapeshellcmd($stream['stream_info']['custom_map']) . ' -copy_unknown '; @@ -277,8 +260,8 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource $analyseDuration = abs(intval(ipTV_lib::$settings['stream_max_analyze'])); $probesize = abs(intval(ipTV_lib::$settings['probesize'])); } - $streamTimeout = intval($analyseDuration / 1000000) + ipTV_lib::$settings["probe_extra_wait"]; - $rFFProbee = "/usr/bin/timeout {$streamTimeout}s " . FFPROBE_PATH . " {FETCH_OPTIONS} -probesize {$probesize} -analyzeduration {$analyseDuration} {CONCAT} -i {STREAM_SOURCE} -v quiet -print_format json -show_streams -show_format"; + $streamTimeout = intval($analyseDuration / 1000000) + ipTV_lib::$settings['probe_extra_wait']; + $rFFProbee = 'timeout ' . $streamTimeout . ' ' . ipTV_lib::$FFPROBE . ' {FETCH_OPTIONS} -probesize ' . $probesize . ' -analyzeduration ' . $analyseDuration . ' {CONCAT} -i {STREAM_SOURCE} -v quiet -print_format json -show_streams -show_format'; $rFetchOptions = array(); $rLoopback = false; $rOffset = 0; @@ -303,7 +286,7 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource $rOffset = $rTimer; $rCCOutput[] = $path; } else { - if ($rTimer + $rDuration < $startPos) { + if ($startPos < $rTimer + $rDuration) { $rCCOutput[] = $path; } } @@ -358,7 +341,7 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource ipTV_lib::$SegmentsSettings['seg_type'] = 1; } if ($stream['stream_info']['type_key'] == 'created_live' && file_exists(CREATED_PATH . $streamID . '_.info')) { - self::$ipTV_db->query('UPDATE `streams_servers` SET `cc_info` = \'%d\' WHERE `server_id` = \'%d\' AND `stream_id` = \'%d\';', file_get_contents(CREATED_PATH . $streamID . '_.info'), SERVER_ID, $streamID); + self::$ipTV_db->query('UPDATE `streams_servers` SET `cc_info` = \'%s\' WHERE `server_id` = \'%d\' AND `stream_id` = \'%d\';', file_get_contents(CREATED_PATH . $streamID . '_.info'), SERVER_ID, $streamID); } if (!$rFromCache) { self::deleteCache($sources); @@ -378,7 +361,6 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource if (!$processed) { $probeArguments[] = array('value' => 'X-XTREAMUI-Prebuffer:1', 'argument_key' => 'headers', 'argument_cat' => 'fetch', 'argument_wprotocol' => 'http', 'argument_type' => 'text', 'argument_cmd' => "-headers '%s" . "\r\n" . "'"); } - $protocol = strtolower(substr($streamSource, 0, strpos($streamSource, '://'))); $probeOptions = implode(' ', self::getFormattedStreamArguments($probeArguments, $protocol, 'fetch')); $rFetchOptions = implode(' ', self::getFormattedStreamArguments($stream['stream_arguments'], $protocol, 'fetch')); @@ -414,11 +396,13 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource } } $rExternalPush = json_decode($stream['stream_info']['external_push'], true); - $progressURL = 'http://127.0.0.1:' . intval(ipTV_lib::$StreamingServers[SERVER_ID]['http_broadcast_port']) . '/progress.php?stream_id=' . intval($streamID); - + $progressURL = 'http://127.0.0.1:' . intval(ipTV_lib::$StreamingServers[SERVER_ID]['http_broadcast_port']) . '/progress?stream_id=' . intval($streamID); if (empty($stream['stream_info']['custom_ffmpeg'])) { - - // set map option ffmpeg + if ($rLoopback) { + $rOptions = '{FETCH_OPTIONS}'; + } else { + $rOptions = '{GPU} {FETCH_OPTIONS}'; + } if ($stream['stream_info']['stream_all'] == 1) { $rMap = '-map 0 -copy_unknown '; } elseif (!empty($stream['stream_info']['custom_map'])) { @@ -428,20 +412,21 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource } else { $rMap = ''; } - - // set timestamps options ffmpeg if (($stream['stream_info']['gen_timestamps'] == 1 || empty($protocol)) && $stream['stream_info']['type_key'] != 'created_live') { $rGenPTS = '-fflags +genpts -async 1'; } else { - $rGenPTS = '-nofix_dts -start_at_zero -copyts -vsync 0 -correct_ts_overflow 0 -avoid_negative_ts disabled -max_interleave_delta 0'; + if (in_array($rFFProbeOutput['codecs']['audio']['codec_name'], array('ac3', 'eac3')) && ipTV_lib::$settings['dts_legacy_ffmpeg']) { + ipTV_lib::$FFMPEG_CPU = FFMPEG_BIN_40; + ipTV_lib::$FFPROBE = FFPROBE_BIN_40; + } + $rNoFix = (ipTV_lib::$FFMPEG_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'; } - - if (!$stream['server_info']['parent_id'] && ($stream['stream_info']['read_native'] == 1 || stristr($rFFProbeOutput['container'], 'hls') || empty($protocol) || stristr($rFFProbeOutput['container'], 'mp4') || stristr($rFFProbeOutput['container'], 'matroska'))) { + if (!$stream['server_info']['parent_id'] && ($stream['stream_info']['read_native'] == 1 || stristr($rFFProbeOutput['container'], 'hls') && ipTV_lib::$settings['read_native_hls'] || empty($protocol) || stristr($rFFProbeOutput['container'], 'mp4') || stristr($rFFProbeOutput['container'], 'matroska'))) { $rReadNative = '-re'; } else { $rReadNative = ''; } - if (!$stream['server_info']['parent_id'] && $stream['stream_info']['enable_transcode'] == 1 && $stream['stream_info']['type_key'] != 'created_live') { if ($stream['stream_info']['transcode_profile_id'] == -1) { $stream['stream_info']['transcode_attributes'] = array_merge(self::getFormattedStreamArguments($stream['stream_arguments'], $protocol, 'transcode'), json_decode($stream['stream_info']['transcode_attributes'], true)); @@ -451,7 +436,7 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource } else { $stream['stream_info']['transcode_attributes'] = array(); } - $rFFMPEG = FFMPEG_PATH . ' -y -nostdin -hide_banner -loglevel ' . ((ipTV_lib::$settings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err {FETCH_OPTIONS} {GEN_PTS} {READ_NATIVE} -probesize ' . $probesize . ' -analyzeduration ' . $analyseDuration . ' -progress "' . $progressURL . '" {CONCAT} -i {STREAM_SOURCE} {LOGO} '; + $rFFMPEG = ((isset($stream['stream_info']['transcode_attributes']['gpu']) ? ipTV_lib::$FFMPEG_GPU : ipTV_lib::$FFMPEG_CPU)) . ' -y -nostdin -hide_banner -loglevel ' . ((ipTV_lib::$settings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -err_detect ignore_err ' . $rOptions . ' {GEN_PTS} {READ_NATIVE} -probesize ' . $probesize . ' -analyzeduration ' . $analyseDuration . ' -progress "' . $progressURL . '" {CONCAT} -i {STREAM_SOURCE} {LOGO} '; if (!array_key_exists('-acodec', $stream['stream_info']['transcode_attributes'])) { $stream['stream_info']['transcode_attributes']['-acodec'] = 'copy'; } @@ -467,31 +452,45 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource } } else { $stream['stream_info']['transcode_attributes'] = array(); - $rFFMPEG = FFMPEG_PATH . ' -y -nostdin -hide_banner -loglevel ' . ((ipTV_lib::$settings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -progress "' . $progressURL . '" ' . $stream['stream_info']['custom_ffmpeg']; + $rFFMPEG = ((stripos($stream['stream_info']['custom_ffmpeg'], 'nvenc') !== false ? ipTV_lib::$FFMPEG_GPU : ipTV_lib::$FFMPEG_CPU)) . ' -y -nostdin -hide_banner -loglevel ' . ((ipTV_lib::$settings['ffmpeg_warnings'] ? 'warning' : 'error')) . ' -progress "' . $progressURL . '" ' . $stream['stream_info']['custom_ffmpeg']; } $rLLODOptions = ($rLLOD && !$rLoopback ? '-fflags nobuffer -flags low_delay -strict experimental' : ''); $rOutputs = array(); - + if ($rLoopback) { + $rOptions = '{MAP}'; + $rFLVOptions = '{MAP}'; + $rMap = '-map 0 -copy_unknown '; + } else { + $rOptions = '{MAP} {LLOD}'; + $rFLVOptions = '{MAP} {AAC_FILTER}'; + } if (ipTV_lib::$SegmentsSettings['seg_type'] == 0) { - $rKeyFrames = (ipTV_lib::$settings["ignore_keyframes"] ? '+split_by_time' : ''); - $rOutputs['mpegts'][] = '{MAP} -individual_header_trailer 0 -f hls -hls_time ' . intval(ipTV_lib::$SegmentsSettings["seg_time"]) . ' -hls_list_size ' . intval(ipTV_lib::$SegmentsSettings["seg_list_size"]) . ' -hls_delete_threshold ' . intval(ipTV_lib::$settings["seg_delete_threshold"]) . ' -hls_flags delete_segments+discont_start+omit_endlist' . $rKeyFrames . ' -hls_segment_type mpegts -hls_segment_filename "' . STREAMS_PATH . intval($streamID) . '_%d.ts" "' . STREAMS_PATH . intval($streamID) . '_.m3u8" '; + $rKeyFrames = (ipTV_lib::$settings['ignore_keyframes'] ? '+split_by_time' : ''); + $rOutputs['mpegts'][] = $rOptions . ' -individual_header_trailer 0 -f hls -hls_time ' . intval(ipTV_lib::$SegmentsSettings['seg_time']) . ' -hls_list_size ' . intval(ipTV_lib::$SegmentsSettings['seg_list_size']) . ' -hls_delete_threshold ' . intval(ipTV_lib::$SegmentsSettings['seg_delete_threshold']) . ' -hls_flags delete_segments+discont_start+omit_endlist' . $rKeyFrames . ' -hls_segment_type mpegts -hls_segment_filename "' . STREAMS_PATH . intval($streamID) . '_%d.ts" "' . STREAMS_PATH . intval($streamID) . '_.m3u8" '; } else { - $rKeyFrames = (ipTV_lib::$settings["ignore_keyframes"] ? ' -break_non_keyframes 1' : ''); - $rOutputs['mpegts'][] = '{MAP} -individual_header_trailer 0 -f segment -segment_format mpegts -segment_time ' . intval(ipTV_lib::$SegmentsSettings["seg_time"]) . ' -segment_list_size ' . intval(ipTV_lib::$SegmentsSettings["seg_list_size"]) . ' -segment_format_options "mpegts_flags=+initial_discontinuity:mpegts_copyts=1" -segment_list_type m3u8 -segment_list_flags +live+delete' . $rKeyFrames . ' -segment_list "' . STREAMS_PATH . intval($streamID) . '_.m3u8" "' . STREAMS_PATH . intval($streamID) . '_%d.ts" '; + $rKeyFrames = (ipTV_lib::$settings['ignore_keyframes'] ? ' -break_non_keyframes 1' : ''); + $rOutputs['mpegts'][] = $rOptions . ' -individual_header_trailer 0 -f segment -segment_format mpegts -segment_time ' . intval(ipTV_lib::$SegmentsSettings['seg_time']) . ' -segment_list_size ' . intval(ipTV_lib::$SegmentsSettings['seg_list_size']) . ' -segment_format_options "mpegts_flags=+initial_discontinuity:mpegts_copyts=1" -segment_list_type m3u8 -segment_list_flags +live+delete' . $rKeyFrames . ' -segment_list "' . STREAMS_PATH . intval($streamID) . '_.m3u8" "' . STREAMS_PATH . intval($streamID) . '_%d.ts" '; } if ($stream['stream_info']['rtmp_output'] == 1) { - $rOutputs['flv'][] = '{MAP} -f flv -flvflags no_duration_filesize rtmp://127.0.0.1:' . intval(ipTV_lib::$StreamingServers[$stream['server_info']['server_id']]['rtmp_port']) . '/live/' . intval($streamID) . '?password=' . urlencode(ipTV_lib::$settings['live_streaming_pass']) . ' '; + $rOutputs['flv'][] = $rFLVOptions . ' -f flv -flvflags no_duration_filesize rtmp://127.0.0.1:' . intval(ipTV_lib::$StreamingServers[$stream['server_info']['server_id']]['rtmp_port']) . '/live/' . intval($streamID) . '?password=' . urlencode(ipTV_lib::$settings['live_streaming_pass']) . ' '; } if (!empty($rExternalPush[SERVER_ID])) { - foreach ($rExternalPush[SERVER_ID] as $pushURL) { - $rOutputs['flv'][] = '{MAP} -f flv -flvflags no_duration_filesize ' . escapeshellarg($pushURL) . ' '; + foreach ($rExternalPush[SERVER_ID] as $rPushURL) { + $rOutputs['flv'][] = $rFLVOptions . ' -f flv -flvflags no_duration_filesize ' . escapeshellarg($rPushURL) . ' '; } } $rLogoOptions = (isset($stream['stream_info']['transcode_attributes'][16]) && !$rLoopback ? $stream['stream_info']['transcode_attributes'][16]['cmd'] : ''); + $rGPUOptions = (isset($stream['stream_info']['transcode_attributes']['gpu']) ? $stream['stream_info']['transcode_attributes']['gpu']['cmd'] : ''); $rInputCodec = ''; + if (!empty($rGPUOptions) || in_array($rFFProbeOutput['codecs']['video']['codec_name'], array('h264', 'hevc', 'mjpeg', 'mpeg1', 'mpeg2', 'mpeg4', 'vc1', 'vp8', 'vp9'))) { + $rInputCodec = '-c:v ' . $rFFProbeOutput['codecs']['video']['codec_name'] . '_cuvid'; + } if (0 >= $stream['stream_info']['delay_minutes'] || $stream['server_info']['parent_id']) { foreach ($rOutputs as $rOutputKey => $rOutputCommands) { foreach ($rOutputCommands as $rOutputCommand) { + if (isset($stream['stream_info']['transcode_attributes']['gpu'])) { + $rFFMPEG .= '-gpu ' . intval($stream['stream_info']['transcode_attributes']['gpu']['device']) . ' '; + } $rFFMPEG .= implode(' ', self::parseTranscode($stream['stream_info']['transcode_attributes'])) . ' '; $rFFMPEG .= $rOutputCommand; } @@ -519,9 +518,9 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource } $rFFMPEG .= implode(' ', self::parseTranscode($stream['stream_info']['transcode_attributes'])) . ' '; if (ipTV_lib::$SegmentsSettings['seg_type'] == 0) { - $rFFMPEG .= '{MAP} -individual_header_trailer 0 -f hls -hls_time ' . intval(ipTV_lib::$SegmentsSettings["seg_time"]) . ' -hls_list_size ' . intval($stream['stream_info']['delay_minutes']) * 6 . ' -hls_delete_threshold 4 -start_number ' . $segmentStart . ' -hls_flags delete_segments+discont_start+omit_endlist -hls_segment_type mpegts -hls_segment_filename "' . DELAY_PATH . intval($streamID) . '_%d.ts" "' . DELAY_PATH . intval($streamID) . '_.m3u8" '; + $rFFMPEG .= '{MAP} -individual_header_trailer 0 -f hls -hls_time ' . intval(ipTV_lib::$SegmentsSettings['seg_time']) . ' -hls_list_size ' . intval($stream['stream_info']['delay_minutes']) * 6 . ' -hls_delete_threshold 4 -start_number ' . $segmentStart . ' -hls_flags delete_segments+discont_start+omit_endlist -hls_segment_type mpegts -hls_segment_filename "' . DELAY_PATH . intval($streamID) . '_%d.ts" "' . DELAY_PATH . intval($streamID) . '_.m3u8" '; } else { - $rFFMPEG .= '{MAP} -individual_header_trailer 0 -f segment -segment_format mpegts -segment_time ' . intval(ipTV_lib::$SegmentsSettings["seg_time"]) . ' -segment_list_size ' . intval($stream['stream_info']['delay_minutes']) * 6 . ' -segment_start_number ' . $segmentStart . ' -segment_format_options "mpegts_flags=+initial_discontinuity:mpegts_copyts=1" -segment_list_type m3u8 -segment_list_flags +live+delete -segment_list "' . DELAY_PATH . intval($streamID) . '_.m3u8" "' . DELAY_PATH . intval($streamID) . '_%d.ts" '; + $rFFMPEG .= '{MAP} -individual_header_trailer 0 -f segment -segment_format mpegts -segment_time ' . intval(ipTV_lib::$SegmentsSettings['seg_time']) . ' -segment_list_size ' . intval($stream['stream_info']['delay_minutes']) * 6 . ' -segment_start_number ' . $segmentStart . ' -segment_format_options "mpegts_flags=+initial_discontinuity:mpegts_copyts=1" -segment_list_type m3u8 -segment_list_flags +live+delete -segment_list "' . DELAY_PATH . intval($streamID) . '_.m3u8" "' . DELAY_PATH . intval($streamID) . '_%d.ts" '; } $sleepTime = $stream['stream_info']['delay_minutes'] * 60; if ($segmentStart > 0) { @@ -533,8 +532,7 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource } } $rFFMPEG .= ' >/dev/null 2>>' . STREAMS_PATH . intval($streamID) . '.errors & echo $! > ' . STREAMS_PATH . intval($streamID) . '_.pid'; - $rFFMPEG = str_replace(array('{FETCH_OPTIONS}', '{GEN_PTS}', '{STREAM_SOURCE}', '{MAP}', '{READ_NATIVE}', '{CONCAT}', '{AAC_FILTER}', '{INPUT_CODEC}', '{LOGO}', '{LLOD}'), array((empty($stream['stream_info']['custom_ffmpeg']) ? $rFetchOptions : ''), (empty($stream['stream_info']['custom_ffmpeg']) ? $rGenPTS : ''), escapeshellarg($streamSource), (empty($stream['stream_info']['custom_ffmpeg']) ? $rMap : ''), (empty($stream['stream_info']['custom_ffmpeg']) ? $rReadNative : ''), ($stream['stream_info']['type_key'] == 'created_live' && !$stream['server_info']['parent_id'] ? '-safe 0 -f concat' : ''), (!stristr($rFFProbeOutput['container'], 'flv') && $rFFProbeOutput['codecs']['audio']['codec_name'] == 'aac' && $stream['stream_info']['transcode_attributes']['-acodec'] == 'copy' ? '-bsf:a aac_adtstoasc' : ''), $rInputCodec, $rLogoOptions, $rLLODOptions), $rFFMPEG); - + $rFFMPEG = str_replace(array('{FETCH_OPTIONS}', '{GEN_PTS}', '{STREAM_SOURCE}', '{MAP}', '{READ_NATIVE}', '{CONCAT}', '{AAC_FILTER}', '{GPU}', '{INPUT_CODEC}', '{LOGO}', '{LLOD}'), array((empty($stream['stream_info']['custom_ffmpeg']) ? $rFetchOptions : ''), (empty($stream['stream_info']['custom_ffmpeg']) ? $rGenPTS : ''), escapeshellarg($streamSource), (empty($stream['stream_info']['custom_ffmpeg']) ? $rMap : ''), (empty($stream['stream_info']['custom_ffmpeg']) ? $rReadNative : ''), ($stream['stream_info']['type_key'] == 'created_live' && !$stream['server_info']['parent_id'] ? '-safe 0 -f concat' : ''), (!stristr($rFFProbeOutput['container'], 'flv') && $rFFProbeOutput['codecs']['audio']['codec_name'] == 'aac' && $stream['stream_info']['transcode_attributes']['-acodec'] == 'copy' ? '-bsf:a aac_adtstoasc' : ''), $rGPUOptions, $rInputCodec, $rLogoOptions, $rLLODOptions), $rFFMPEG); shell_exec($rFFMPEG); file_put_contents(STREAMS_PATH . $streamID . '_.ffmpeg', $rFFMPEG); $rKey = openssl_random_pseudo_bytes(16); @@ -546,12 +544,26 @@ public static function startStream($streamID, $rFromCache = false, $rForceSource if ($stream['stream_info']['tv_archive_server_id'] == SERVER_ID) { shell_exec(PHP_BIN . ' ' . TOOLS_PATH . 'archive.php ' . intval($streamID) . ' >/dev/null 2>/dev/null & echo $!'); } + // if ($stream['stream_info']['vframes_server_id'] == SERVER_ID) { + // self::startThumbnail($streamID); + // } $rDelayEnabled = 0 < $stream['stream_info']['delay_minutes'] && !$stream['server_info']['parent_id']; $rDelayStartAt = ($rDelayEnabled ? time() + $sleepTime : 0); if ($stream['stream_info']['enable_transcode']) { $rFFProbeOutput = array(); } - self::$ipTV_db->query('UPDATE `streams_servers` SET `delay_available_at` = \'%d\',`to_analyze` = 0,`stream_started` = \'%d\',`stream_info` = \'%d\', `stream_status` = 2,`pid` = \'%d\',`progress_info` = \'%d\',`current_source` = \'%d\' WHERE `stream_id` = \'%d\' AND `server_id` = \'%d\'', $rDelayStartAt, time(), json_encode($rFFProbeOutput), $pID, json_encode(array()), $source, $streamID, SERVER_ID); + $rCompatible = 0; + $rAudioCodec = $rVideoCodec = $rResolution = null; + if ($rFFProbeOutput) { + $rCompatible = intval(self::checkCompatibility($rFFProbeOutput)); + $rAudioCodec = ($rFFProbeOutput['codecs']['audio']['codec_name'] ?: null); + $rVideoCodec = ($rFFProbeOutput['codecs']['video']['codec_name'] ?: null); + $rResolution = ($rFFProbeOutput['codecs']['video']['height'] ?: null); + if ($rResolution) { + $rResolution = self::getNearest(array(240, 360, 480, 576, 720, 1080, 1440, 2160), $rResolution); + } + } + self::$ipTV_db->query('UPDATE `streams_servers` SET `delay_available_at` = \'%d\',`to_analyze` = 0,`stream_started` = \'%d\',`stream_info` = \'%d\',`audio_codec` = \'%d\', `video_codec` = \'%d\', `resolution` = \'%d\',`compatible` = \'%d\',`stream_status` = 2,`pid` = \'%d\',`progress_info` = \'%d\',`current_source` = \'%d\' WHERE `stream_id` = \'%d\' AND `server_id` = \'%d\'', $rDelayStartAt, time(), json_encode($rFFProbeOutput), $rAudioCodec, $rVideoCodec, $rResolution, $rCompatible, $pID, json_encode(array()), $source, $streamID, SERVER_ID); ipTV_streaming::updateStream($streamID); $playlist = (!$rDelayEnabled ? STREAMS_PATH . $streamID . '_.m3u8' : DELAY_PATH . $streamID . '_.m3u8'); return array('main_pid' => $pID, 'stream_source' => $rRealSource, 'delay_enabled' => $rDelayEnabled, 'parent_id' => $stream['server_info']['parent_id'], 'delay_start_at' => $rDelayStartAt, 'playlist' => $playlist, 'transcode' => $stream['stream_info']['enable_transcode'], 'offset' => $rOffset); @@ -712,4 +724,68 @@ public static function getURL($rURL, $rWait = true) { curl_close($ch); return $rReturn; } + /** + * The function `checkCompatibility` checks if the audio and video codecs in the provided data are + * compatible with the predefined arrays of supported codecs. + * + * @param array rData is expected to be an array containing information about audio and video codecs. + * If is not an array, the function attempts to decode it from JSON format. The function then + * checks if the audio and video codec names in the array are compatible with the predefined + * lists of supported + * + * @return bool The function `checkCompatibility` is returning a boolean value based on the conditions + * specified in the code. It checks if the input `` contains audio and video codec names that are + * present in the predefined arrays `` and `` respectively. If the codec + * names are found and meet the conditions, it returns `true`, otherwise it returns `false`. + */ + public static function checkCompatibility($rData) { + if (!is_array($rData)) { + $rData = json_decode($rData, true); + } + $rAudioCodecs = array('aac', 'libfdk_aac', 'opus', 'vorbis', 'pcm_s16le', 'mp2', 'mp3', 'flac', null); + $rVideoCodecs = array('h264', 'vp8', 'vp9', 'ogg', 'av1', null); + if (ipTV_lib::$settings['player_allow_hevc']) { + $rVideoCodecs[] = 'hevc'; + $rVideoCodecs[] = 'h265'; + $rAudioCodecs[] = 'ac3'; + } + return ($rData['codecs']['audio']['codec_name'] || $rData['codecs']['video']['codec_name']) && in_array(strtolower($rData['codecs']['audio']['codec_name']), $rAudioCodecs) && in_array(strtolower($rData['codecs']['video']['codec_name']), $rVideoCodecs); + } + /** + * Finds the nearest value in an array to a given search value. + * + * This method iterates through an array and finds the element that is + * closest in value to the given search parameter. It works with numeric values. + * + * @param array $arr The input array of numbers to search through. + * @param float $search The value to find the nearest match for. + * + * @return float|int|null The nearest value found in the array. Returns null if the array is empty. + */ + public static function getNearest($arr, $search) { + $closest = null; + foreach ($arr as $item) { + if ($closest === null || abs($item - $search) < abs($search - $closest)) { + $closest = $item; + } + } + return $closest; + } + /** + * Deletes files based on the provided sources. + * + * This function takes an array of file sources and deletes the corresponding files from the STREAMS_PATH directory if they exist. + * + * @param array $sources An array of file sources to be deleted. + * @return void + */ + static function deleteCache($sources) { + if (!empty($sources)) { + foreach ($sources as $source) { + ipTV_lib::unlink_file(STREAMS_PATH . md5($source)); + } + } else { + return null; + } + } } diff --git a/wwwdir/includes/streaming.php b/wwwdir/includes/streaming.php index 2022f108..f98263ec 100644 --- a/wwwdir/includes/streaming.php +++ b/wwwdir/includes/streaming.php @@ -14,12 +14,12 @@ public static function sendSignalFFMPEG($signalData, $segmentFile, $codec = 'h26 } if ($return) { $rOutput = SIGNALS_PATH . $signalData['activity_id'] . '_' . $segmentFile; - shell_exec(FFMPEG_PATH . ' -copyts -vsync 0 -nostats -nostdin -hide_banner -loglevel quiet -y -i ' . escapeshellarg(STREAMS_PATH . $segmentFile) . ' -filter_complex "drawtext=fontfile=' . FFMPEG_FONTS_PATH . ":text='" . escapeshellcmd($signalData['message']) . "':fontsize=" . escapeshellcmd($signalData['font_size']) . ':x=' . intval($x) . ':y=' . intval($y) . ':fontcolor=' . escapeshellcmd($signalData['font_color']) . '" -map 0 -vcodec ' . $codec . ' -preset ultrafast -acodec copy -scodec copy -mpegts_flags +initial_discontinuity -mpegts_copyts 1 -f mpegts ' . escapeshellarg($rOutput)); + shell_exec(ipTV_lib::$FFMPEG_CPU . ' -copyts -vsync 0 -nostats -nostdin -hide_banner -loglevel quiet -y -i ' . escapeshellarg(STREAMS_PATH . $segmentFile) . ' -filter_complex "drawtext=fontfile=' . FFMPEG_FONTS_PATH . ":text='" . escapeshellcmd($signalData['message']) . "':fontsize=" . escapeshellcmd($signalData['font_size']) . ':x=' . intval($x) . ':y=' . intval($y) . ':fontcolor=' . escapeshellcmd($signalData['font_color']) . '" -map 0 -vcodec ' . $codec . ' -preset ultrafast -acodec copy -scodec copy -mpegts_flags +initial_discontinuity -mpegts_copyts 1 -f mpegts ' . escapeshellarg($rOutput)); $data = file_get_contents($rOutput); ipTV_lib::unlink_file($rOutput); return $data; } - passthru(FFMPEG_PATH . ' -copyts -vsync 0 -nostats -nostdin -hide_banner -loglevel quiet -y -i ' . escapeshellarg(STREAMS_PATH . $segmentFile) . ' -filter_complex "drawtext=fontfile=' . FFMPEG_FONTS_PATH . ":text='" . escapeshellcmd($signalData['message']) . "':fontsize=" . escapeshellcmd($signalData['font_size']) . ':x=' . intval($x) . ':y=' . intval($y) . ':fontcolor=' . escapeshellcmd($signalData['font_color']) . '" -map 0 -vcodec ' . $codec . ' -preset ultrafast -acodec copy -scodec copy -mpegts_flags +initial_discontinuity -mpegts_copyts 1 -f mpegts -'); + passthru(ipTV_lib::$FFMPEG_CPU . ' -copyts -vsync 0 -nostats -nostdin -hide_banner -loglevel quiet -y -i ' . escapeshellarg(STREAMS_PATH . $segmentFile) . ' -filter_complex "drawtext=fontfile=' . FFMPEG_FONTS_PATH . ":text='" . escapeshellcmd($signalData['message']) . "':fontsize=" . escapeshellcmd($signalData['font_size']) . ':x=' . intval($x) . ':y=' . intval($y) . ':fontcolor=' . escapeshellcmd($signalData['font_color']) . '" -map 0 -vcodec ' . $codec . ' -preset ultrafast -acodec copy -scodec copy -mpegts_flags +initial_discontinuity -mpegts_copyts 1 -f mpegts -'); return true; } public static function getAllowedIPsAdmin($rForce = false) { @@ -1074,7 +1074,7 @@ public static function B97D7ACBCf7c7A5e($video_path_id) { } } public static function IsValidStream($playlist, $PID) { - return self::isProcessRunning($PID, FFMPEG_PATH) && file_exists($playlist); + return self::isProcessRunning($PID, ipTV_lib::$FFMPEG_CPU) && file_exists($playlist); } public static function getUserIP() { if (!empty($_SERVER['HTTP_CLIENT_IP'])) { diff --git a/wwwdir/streaming/admin_live.php b/wwwdir/streaming/admin_live.php index e606db8e..a817b155 100644 --- a/wwwdir/streaming/admin_live.php +++ b/wwwdir/streaming/admin_live.php @@ -104,7 +104,7 @@ echo $data; $fails = 0; } - if (ipTV_streaming::isProcessRunning($channel_info["pid"], FFMPEG_PATH) && $fails <= $total_failed_tries && file_exists(STREAMS_PATH . $segment_file) && is_resource($fp)) { + if (ipTV_streaming::isProcessRunning($channel_info["pid"], ipTV_lib::$FFMPEG_CPU) && $fails <= $total_failed_tries && file_exists(STREAMS_PATH . $segment_file) && is_resource($fp)) { $size = filesize(STREAMS_PATH . $segment_file); $line = $size - ftell($fp); if ($line > 0) { diff --git a/wwwdir/streaming/rtmp.php b/wwwdir/streaming/rtmp.php index 88a0b6f3..62083c64 100644 --- a/wwwdir/streaming/rtmp.php +++ b/wwwdir/streaming/rtmp.php @@ -113,7 +113,7 @@ } if ($channel_info = ipTV_streaming::ChannelInfo($stream_id, $extension, $user_info, $user_ip, $geoip_country_code, $external_device, $user_info['con_isp_name'], 'live')) { $playlist = STREAMS_PATH . $stream_id . '_.m3u8'; - if (!ipTV_streaming::isProcessRunning($channel_info['pid'], FFMPEG_PATH) && $channel_info['on_demand'] == 1) { + if (!ipTV_streaming::isProcessRunning($channel_info['pid'], ipTV_lib::$FFMPEG_CPU) && $channel_info['on_demand'] == 1) { ipTV_stream::startMonitor($stream_id); sleep(5); }