1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-05 19:42:38 +02:00

Encoder now log information, improve socket

This commit is contained in:
Daniel Neto 2024-05-23 09:21:02 -03:00
parent 372b2e1283
commit 2c4e22b99d
16 changed files with 319 additions and 82 deletions

View file

@ -120,9 +120,20 @@ http {
root html;
}
location /control {
# replace this with the IP of your AVideo site
# Allow localhost and internal Docker network
allow 127.0.0.1;
allow localhost;
# Allow requests from the 'live' service
allow live;
# Allow requests from the internal Docker network (e.g., 172.18.0.0/16)
allow 172.18.0.0/16;
# Deny all other requests
deny all;
# RTMP control settings
rtmp_control all;
}
#allows us to host some webpages which can show our videos: "http://my-ip/my-page.html"

View file

@ -0,0 +1,81 @@
<?php
/*
error_log("avideoencoder REQUEST 1: " . json_encode($_REQUEST));
error_log("avideoencoder POST 1: " . json_encode($_REQUEST));
error_log("avideoencoder GET 1: " . json_encode($_GET));
*/
if (empty($global)) {
$global = [];
}
$obj = new stdClass();
$obj->error = true;
global $global, $config;
if (!isset($global['systemRootPath'])) {
require_once '../videos/configuration.php';
}
inputToRequest();
/*
_error_log("REQUEST: " . json_encode($_REQUEST));
_error_log("POST: " . json_encode($_REQUEST));
_error_log("GET: " . json_encode($_GET));
*/
header('Content-Type: application/json');
allowOrigin();
$global['bypassSameDomainCheck'] = 1;
if (empty($_REQUEST)) {
$obj->msg = ("Your POST data is empty, maybe your video file is too big for the host");
_error_log($obj->msg);
forbiddenPage($obj->msg);
}
//_error_log("aVideoEncoderLog.json: start");
_error_log("aVideoEncoderLog.json: start");
if (!isset($_REQUEST['encodedPass'])) {
$_REQUEST['encodedPass'] = 1;
}
useVideoHashOrLogin();
if (!User::canUpload()) {
$obj->msg = __("Permission denied to receive a file") . ': ' . json_encode($_REQUEST);
_error_log("aVideoEncoderLog.json: {$obj->msg} " . json_encode(User::canNotUploadReason()));
_error_log($obj->msg);
forbiddenPage($obj->msg);
}
$obj->videos_id = intval($_REQUEST['videos_id']);
if (empty($obj->videos_id)) {
$obj->msg = "Videos_id is required ";
_error_log($obj->msg . json_encode($_REQUEST));
forbiddenPage($obj->msg);
}
if (!Video::canEdit($obj->videos_id)) {
$obj->msg = "You cannot edit videos_id " . $obj->videos_id;
_error_log($obj->msg . json_encode($_REQUEST));
forbiddenPage($obj->msg);
}
_error_log("aVideoEncoderLog.json: start to receive: " . json_encode($_REQUEST));
// check if there is en video id if yes update if is not create a new one
$video = new Video("", "", $obj->videos_id, true);
$externalOptions = _json_decode($video->getExternalOptions());
if (empty($externalOptions)) {
$externalOptions = new stdClass();
}
if (empty($externalOptions->encoderLog)) {
$externalOptions->encoderLog = array();
}
$externalOptions->encoderLog[] = array('msg' => $_REQUEST['msg'], 'type' => $_REQUEST['type'], 'time' => time(), 'datetime'=>date('Y-m-d H:i:s'));
$video->setExternalOptions(json_encode($externalOptions));
$obj->saved = $video->save();
$obj->error = empty($obj->saved);
echo json_encode($obj);

View file

@ -247,48 +247,15 @@ function getPIDUsingPort($port)
return false;
}
function execAsync($command)
function canExecutePgrep()
{
//$command = escapeshellarg($command);
// If windows, else
if (isWindows()) {
//echo $command;
//$pid = system("start /min ".$command. " > NUL");
//$commandString = "start /B " . $command;
//pclose($pid = popen($commandString, "r"));
_error_log($command);
$pid = exec($command, $output, $retval);
_error_log('execAsync Win: ' . json_encode($output) . ' ' . $retval);
} else {
$newCommand = $command . " > /dev/null 2>&1 & echo $!; ";
_error_log('execAsync Linux: ' . $newCommand);
$pid = exec($newCommand);
}
return $pid;
}
function killProcess($pid)
{
$pid = intval($pid);
if (empty($pid)) {
return false;
}
if (isWindows()) {
exec("taskkill /F /PID $pid");
} else {
exec("kill -9 $pid");
}
return true;
}
function canExecutePgrep() {
// Check if we can successfully pgrep the init or systemd process
$test = shell_exec('pgrep -f init || pgrep -f systemd');
return !empty($test); // Return true if we can execute pgrep, false otherwise
}
function getProcessPids($processName) {
function getProcessPids($processName)
{
if (!canExecutePgrep()) {
return null; // If we can't execute pgrep, return null
}
@ -318,7 +285,8 @@ function getProcessPids($processName) {
return $pids;
}
function getCommandByPid($pid) {
function getCommandByPid($pid)
{
$cmdlineFile = "/proc/{$pid}/cmdline";
// Check if the cmdline file exists for the given PID
@ -337,3 +305,142 @@ function getCommandByPid($pid) {
return $cmdArray;
}
function execAsync($command, $keyword = null)
{
if ($keyword) {
// Sanitize the keyword to make it a valid filename
$keyword = preg_replace('/[^a-zA-Z0-9_-]/', '_', $keyword);
}
if (isWindows()) {
if ($keyword) {
// Add the keyword as a comment to the command for Windows
$commandWithKeyword = "start /B cmd /c \"$command & REM $keyword\" > NUL 2>&1";
} else {
$commandWithKeyword = "start /B cmd /c \"$command\" > NUL 2>&1";
}
_error_log($commandWithKeyword);
$pid = exec($commandWithKeyword, $output, $retval);
if ($retval !== 0) {
_error_log('execAsync Win Error: ' . json_encode($output) . ' Return Value: ' . $retval);
} else {
_error_log('execAsync Win: ' . json_encode($output) . ' ' . $retval);
}
} else {
if ($keyword) {
// Add the keyword as a comment to the command for Linux
$commandWithKeyword = "nohup sh -c \"$command & echo \\$! > /tmp/$keyword.pid\" > /dev/null 2>&1 &";
} else {
$commandWithKeyword = "nohup sh -c \"$command & echo \\$!\" > /dev/null 2>&1 &";
}
_error_log('execAsync Linux: ' . $commandWithKeyword);
exec($commandWithKeyword, $output, $retval);
_error_log('Command output: ' . json_encode($output));
_error_log('Return value: ' . $retval);
if ($retval !== 0) {
_error_log('execAsync Linux Error: ' . json_encode($output) . ' Return Value: ' . $retval);
} else {
if ($keyword) {
$pidFile = "/tmp/$keyword.pid";
_error_log('Checking PID file: ' . $pidFile);
sleep(1); // Wait a bit to ensure the PID file is written
if (file_exists($pidFile) && filesize($pidFile) > 0) {
$pid = (int)file_get_contents($pidFile);
_error_log('PID file exists, PID: ' . $pid);
} else {
_error_log('PID file does not exist or is empty. Using output[0].');
if (!empty($output[0])) {
$pid = (int)$output[0];
_error_log('PID from output[0]: ' . $pid);
// Save the PID to the file as a fallback
file_put_contents($pidFile, $pid);
_error_log('PID saved to file: ' . $pidFile);
} else {
_error_log('Output[0] is also empty. Unable to determine PID.');
$pid = null;
}
}
} else {
$pid = (int)$output[0];
}
}
}
return $pid;
}
// Function to find the process by keyword using the pid file
function findProcess($keyword)
{
$output = [];
if ($keyword) {
// Sanitize the keyword to make it a valid filename
$keyword = preg_replace('/[^a-zA-Z0-9_-]/', '_', $keyword);
}
// Use pgrep to find processes with the keyword (case insensitive)
exec("pgrep -fai " . escapeshellarg($keyword), $pgrepOutput, $retval);
//var_dump($pgrepOutput);
if ($retval === 0) {
foreach ($pgrepOutput as $pgrepPid) {
if(preg_match('/pgrep /i', $pgrepPid)){
continue;
}
if(preg_match('/([0-9]+) (.*)/i', $pgrepPid, $matches)){
if(!empty($matches[2])){
$output[] = array('pid'=>(int)$matches[1], 'command'=>trim($matches[2]));
}
}
//$output[] = (int)$pgrepPid;
//$output[] = $pgrepPid;
}
}
// Remove duplicate PIDs
$output = array_unique($output);
return $output; // Returns an array of PIDs
}
// Function to kill the process by keyword using the pid file
function killProcessFromKeyword($keyword)
{
$pids = findProcess($keyword);
_error_log("killProcessFromKeyword($keyword) findProcess " . json_encode($pids));
foreach ($pids as $pid) {
killProcess($pid);
}
}
function killProcess($pid)
{
if (is_array($pid)) {
$pid = $pid['pid'];
}
$pid = intval($pid);
if (empty($pid)) {
_error_log("killProcess: Invalid PID $pid");
return false;
}
_error_log("killProcess($pid)");
if (isWindows()) {
$cmd = "taskkill /F /PID $pid";
} else {
$cmd = "kill -9 $pid";
}
_error_log("Executing command: $cmd");
exec($cmd, $output, $retval);
if ($retval === 0) {
_error_log("killProcess: Successfully killed process $pid");
return true;
} else {
_error_log("killProcess: Failed to kill process $pid. Command output: " . json_encode($output) . " Return value: $retval");
return false;
}
}

View file

@ -83,6 +83,10 @@ function _error_log_debug($message, $show_args = false)
function _error_log($message, $type = 0, $doNotRepeat = false)
{
if (!is_string($message)) {
$message = json_encode($message);
}
if(isSchedulerRun()){
echo $message.PHP_EOL;
return false;
@ -98,9 +102,6 @@ function _error_log($message, $type = 0, $doNotRepeat = false)
if (!empty($global['noDebug']) && $type == 0) {
return false;
}
if (!is_string($message)) {
$message = json_encode($message);
}
$prefix = "AVideoLog::";
switch ($type) {
case AVideoLog::$DEBUG:

View file

@ -235,7 +235,10 @@ if (Permissions::canAdminVideos()) {
}
$rowsPath[] = array('line'=>__LINE__, 'ElapsedTime'=>getElapsedTime());
_error_log('Saving video start');
AVideoPlugin::saveVideosAddNew($_POST, $resp);
_error_log('Saving video end');
$rowsPath[] = array('line'=>__LINE__, 'ElapsedTime'=>getElapsedTime());
TimeLogEnd(__FILE__, __LINE__);
@ -249,10 +252,13 @@ $obj->videos_id = intval($resp);
$obj->video = Video::getVideoLight($obj->videos_id, true);
if ($obj->video['status'] == Video::$statusActive) {
$rowsPath[] = array('line'=>__LINE__, 'ElapsedTime'=>getElapsedTime());
_error_log('clearFirstPageCache start');
$obj->clearFirstPageCache = clearFirstPageCache();
_error_log('clearFirstPageCache end');
//clearAllUsersSessionCache();
}
$rowsPath[] = array('line'=>__LINE__, 'ElapsedTime'=>getElapsedTime());
$obj->rowsPath = $rowsPath;
TimeLogEnd(__FILE__, __LINE__);
_error_log('video add new done end');
echo json_encode($obj);

View file

@ -884,8 +884,9 @@ class AVideoPlugin
return false;
}
$plugins = Plugin::getAllEnabled();
foreach ($plugins as $value) {
foreach ($plugins as $key => $value) {
self::YPTstart();
//error_log("{$key} onNewVideo {$value['dirName']} load");
$p = static::loadPlugin($value['dirName']);
if (is_object($p)) {
$p->onNewVideo($videos_id);
@ -3115,6 +3116,23 @@ class AVideoPlugin
self::YPTend("{$value['dirName']}::" . __FUNCTION__);
}
}
public static function canRecordVideo($key)
{
$plugins = Plugin::getAllEnabled();
foreach ($plugins as $value) {
self::YPTstart();
$p = static::loadPlugin($value['dirName']);
if (is_object($p)) {
if(!$p->canRecordVideo($key)){
_error_log("{$value['dirName']} said you cannot record this key $key");
return false;
}
}
self::YPTend("{$value['dirName']}::" . __FUNCTION__);
}
return true;
}
}
class YouPHPTubePlugin extends AVideoPlugin

View file

@ -994,6 +994,9 @@ Click <a href=\"{link}\">here</a> to join our live.";
public static function getControlOrPublic($key, $live_servers_id = 0)
{
global $global;
if(isDocker()){
return 'http://live:8080/control/drop/publisher';
}
$obj = AVideoPlugin::getObjectData("Live");
if (empty($obj->server_type->value)) {
$row = LiveTransmitionHistory::getLatest($key, $live_servers_id);
@ -1365,7 +1368,7 @@ Click <a href=\"{link}\">here</a> to join our live.";
public static function getKeyFromUser($users_id, $doNotCheckUser = false)
{
if (!$doNotCheckUser && (!User::isLogged() || ($users_id !== User::getId() && !User::isAdmin()))) {
if (!isCommandLineInterface() && !$doNotCheckUser && (!User::isLogged() || ($users_id !== User::getId() && !User::isAdmin()))) {
return false;
}
$user = new User($users_id);

View file

@ -321,6 +321,10 @@ class Playlists_schedules extends ObjectYPT
return "ps-{$playlists_schedules}";
}
function canRecordVideo($key) {
return empty(Playlists_schedules::iskeyPlayListScheduled($key));
}
static function iskeyPlayListScheduled($key){
if(preg_match('/([0-9a-z]+)-ps-([0-9]+)/', $key, $matches)){
if(!empty($matches[2])){

View file

@ -126,8 +126,8 @@ if (PlayLists::canManagePlaylist($playlists_id)) {
?>
<button class="btn btn-xs btn-danger deletePlaylist" playlist_id="<?php echo $program['id']; ?>" data-toggle="tooltip" title="<?php echo __('Delete'); ?>"><i class="fas fa-trash"></i> <span class="hidden-xs hidden-sm"><?php echo __("Delete"); ?></span></button>
<button class="btn btn-xs btn-primary renamePlaylist" playlist_id="<?php echo $program['id']; ?>" data-toggle="tooltip" title="<?php echo __('Rename'); ?>"><i class="fas fa-edit"></i> <span class="hidden-xs hidden-sm"><?php echo __("Rename"); ?></span></button>
<button class="btn btn-xs btn-success" onclick="openVideoSearch(<?php echo $currentSerieVideos_id; ?>)" playlist_id="<?php echo $program['id']; ?>" data-toggle="tooltip" title="<?php echo __('Add to Program'); ?>"><span class="fas fa-cog"></span> <span class="hidden-xs hidden-sm"><?php echo __("Add"); ?></span></button>
<button class="btn btn-xs btn-success" onclick="encodeNewVideo()" playlist_id="<?php echo $program['id']; ?>" data-toggle="tooltip" title="<?php echo __('Encode a new video'); ?>"><i class="fas fa-plus"></i> <span class="hidden-xs hidden-sm"><?php echo __("Encode"); ?></span></button>
<button class="btn btn-xs btn-success" onclick="openVideoSearch(<?php echo $currentSerieVideos_id; ?>)" playlist_id="<?php echo $program['id']; ?>" data-toggle="tooltip" title="<?php echo __('Add to Program'); ?>"><span class="fas fa-plus"></span> <span class="hidden-xs hidden-sm"><?php echo __("Add"); ?></span></button>
<button class="btn btn-xs btn-success" onclick="encodeNewVideo()" playlist_id="<?php echo $program['id']; ?>" data-toggle="tooltip" title="<?php echo __('Encode a new video'); ?>"><i class="fas fa-cog"></i> <span class="hidden-xs hidden-sm"><?php echo __("Encode"); ?></span></button>
<button class="btn btn-xs btn-default statusPlaylist statusPlaylist<?php echo $program['id']; ?>" playlist_id="<?php echo $program['id']; ?>" style="">
<span class="fa fa-lock" id="statusPrivate<?php echo $program['id']; ?>" style="color: red; <?php
if ($program['status'] !== 'private') {

View file

@ -909,6 +909,10 @@ abstract class PluginAbstract {
return "";
}
function canRecordVideo($key) {
return true;
}
}
class PluginPermissionOption {

View file

@ -128,8 +128,10 @@ class UserNotifications extends PluginAbstract {
public static function notifySocket($array, $to_users_id = 0) {
if (!empty($to_users_id)) {
//error_log('notifySocket line='.__LINE__);return false;
$socketObj = sendSocketMessageToUsers_id($array, $to_users_id, 'socketUserNotificationCallback');
} else {
//error_log('notifySocket line='.__LINE__);return false;
$socketObj = sendSocketMessageToAll($array, 'socketUserNotificationCallback');
}
return $socketObj;

View file

@ -478,7 +478,7 @@ class Message implements MessageComponentInterface {
unset($this->clients[$client['resourceId']]);
}
if($client['isCommandLine']){
if($client['time']+60 < $time){
if($client['time']+60 < $time && !empty($this->clients) && !empty($this->clients[$client['resourceId']])){
_error_log("resourceId={$client['resourceId']} disconnect commandline after 1 min");
$this->clients[$client['resourceId']]->close();
unset($this->clients[$client['resourceId']]);

View file

@ -179,63 +179,59 @@ class YPTSocket extends PluginAbstract
require_once $global['systemRootPath'] . 'objects/autoload.php';
$SocketURL = self::getWebSocketURL(true, $SocketSendObj->webSocketToken, isDocker());
_error_log("Socket Send: {$SocketURL}");
//_error_log("Socket Send: {$SocketURL}");
\Ratchet\Client\connect($SocketURL)->then(function ($conn) use ($SocketSendUsers_id, $SocketSendObj, $SocketSendResponseObj) {
global $SocketSendResponseObj;
_error_log("Socket line=" . __LINE__);
$conn->on('message', function ($msg) use ($conn, $SocketSendResponseObj) {
_error_log("Socket on message line=" . __LINE__ . ' ' . json_encode($msg));
$SocketSendResponseObj->error = false;
$SocketSendResponseObj->msg = $msg;
});
// Log when the connection is closed
$conn->on('close', function ($code = null, $reason = null) {
_error_log("Socket connection closed. Code: $code, Reason: $reason line=" . __LINE__);
});
$sendMessages = function ($users, $index = 0) use ($conn, $SocketSendObj, &$sendMessages) {
_error_log("Socket sendMessages $index line=" . __LINE__);
if ($index < count($users)) {
_error_log("Socket sendMessages $index line=" . __LINE__);
$SocketSendObj->to_users_id = $users[$index];
$conn->send(json_encode($SocketSendObj), function () use ($users, $index, $sendMessages) {
$sendMessages($users, $index + 1);
_error_log("Socket sendMessages $index total=" . count($users) . " line=" . __LINE__);
//$sendMessages($users, $index + 1);
});
if ($index + 1 >= count($users)) {
_error_log("Socket close $index total=" . count($users) . " line=" . __LINE__);
$conn->close();
} else {
_error_log("Socket sendMessages $index total=" . count($users) . " line=" . __LINE__);
$sendMessages($users, $index + 1);
}
} else {
_error_log("Socket close line=" . __LINE__);
$conn->close();
}
_error_log("Socket sendMessages $index line=" . __LINE__);
};
_error_log("Socket connect line=" . __LINE__);
$sendMessages($SocketSendUsers_id);
}, function ($e) {
global $SocketURL;
_error_log("Could not connect: {$e->getMessage()} {$SocketURL}", AVideoLog::$ERROR);
_error_log("Could not connect: {$e->getMessage()} {$SocketURL} line=" . __LINE__, AVideoLog::$ERROR);
});
/*
$SocketURL = self::getWebSocketURL(true, $SocketSendObj->webSocketToken, isDocker());
//_error_log("Socket Send: {$SocketURL}");
\Ratchet\Client\connect($SocketURL)->then(function ($conn) {
global $SocketSendObj, $SocketSendUsers_id, $SocketSendResponseObj;
$conn->on('message', function ($msg) use ($conn, $SocketSendResponseObj) {
//echo "Received: {$msg}".PHP_EOL;
$SocketSendResponseObj->error = false;
$SocketSendResponseObj->msg = $msg;
//$conn->close();
});
foreach ($SocketSendUsers_id as $users_id) {
$SocketSendObj->to_users_id = $users_id;
$conn->send(json_encode($SocketSendObj));
//echo "send: {$users_id}".PHP_EOL;
}
$conn->close();
//echo "close".PHP_EOL;
//$SocketSendResponseObj->error = false;
}, function ($e) {
global $SocketURL;
_error_log("Could not connect: {$e->getMessage()} {$SocketURL}", AVideoLog::$ERROR);
});
*/
_error_log("Socket SocketSendResponseObj line=" . __LINE__);
return $SocketSendResponseObj;
}
public static function getWebSocketURL($isCommandLine = false, $webSocketToken = '', $internalDocker = false)
{
global $global;

View file

@ -49,7 +49,7 @@ function socketConnect() {
}
conn.onmessage = function (e) {
var json = JSON.parse(e.data);
consolelog("Socket onmessage conn.onmessage", json);
//console.log("Socket onmessage conn.onmessage", json);
socketResourceId = json.resourceId;
yptSocketResponse = json;
parseSocketResponse();
@ -81,12 +81,13 @@ function socketConnect() {
if (json.callback) {
//console.log("Socket onmessage json.callback ", json.resourceId, json.callback);
var code = "if(typeof " + json.callback + " == 'function'){myfunc = " + json.callback + ";}else{myfunc = defaultCallback;}";
////console.log(code);
//console.log(code);
eval(code);
} else {
//console.log("onmessage: callback not found", json);
myfunc = defaultCallback;
}
//console.log("onmessage: callback ", myfunc, json);
myfunc(json.msg);
}
};

View file

@ -723,6 +723,9 @@ if (empty($advancedCustom->disableHTMLDescription)) {
if (response.encoding && response.encoding.length) {
for (i = 0; i < response.encoding.length; i++) {
var encoding = response.encoding[i];
if(typeof encoding.return_vars === 'undefined'){
continue;
}
var id = encoding.return_vars.videos_id;
$("#downloadProgress" + id).slideDown();
var download_status = response.download_status[i];