I'm trying to save the information that ffmpeg sends to the php script but it doesn't work:
// progress.php
ignore_user_abort(true);
$json = file_get_contents('php://input');
if ($_SERVER['REMOTE_ADDR'] != '127.0.0.1' || empty($_GET['stream_id']) || empty($json)) {
die;
}
$stream_id = intval($_GET['stream_id']);
$data = array_filter(array_map('trim', explode(' ', $json)));
$output = array();
foreach ($data as $row) {
list($key, $value) = explode('=', $row);
$output[trim($key)] = trim($value);
}
$fp = fopen("/var/www/html/streams/{$stream_id}_.progress", 'w');
fwrite($fp, json_encode($output));
fclose($fp);
?>
file : 2_.progress
{"frame":"1\nfps","11x\nprogress":"continue\nframe","2.6x\nprogress":"continue\nframe","2x\nprogress":"continue\nframe","1.4x\nprogress":"continue\nframe","1.3x\nprogress":"continue\nframe","1.2x\nprogress":"continue\nframe"}
ffmpeg command :
ffmpeg -y -nostdin -hide_banner -loglevel info -err_detect ignore_err -fflags +genpts -async 1 -user-agent "Restream Panel" -probesize 5000000 -analyzeduration 5000000 -progress "http://127.0.0.1/progress.php?stream_id=2" -i "https://dmitnthvll.cdn.mangomolo.com/dubaisports/smil:dubaisports.smil/chunklist_b1600000.m3u8" -vcodec copy -scodec copy -acodec copy -map 0 -copy_unknown -individual_header_trailer 0 -f segment -segment_list /var/www/html/streams/2_.m3u8 -segment_list_flags +live -segment_list_size 6 -segment_format mpegts -segment_wrap 6 -segment_time 10 /var/www/html/streams/2_%03d.ts
I noticed that if i close ffmpeg it goes to write the .progress file, is there a way to get this info in real time?
Related
I am trying to transfer an mp4 file to Telegram RTMP live using the following command:
$cmd = "ffmpeg -i video.mp4 -c:v libx264 -c:a aac -b:v 2000k -f flv " . $url . $key . "";
exec($cmd, $output, $return);
$url and $key values obtained using MadelineProto for the channel. No picture or sound appears.
Creating a broadcast in the channel and receiving rtmp data accordingly. Everything is clear here
$Updates = $MadelineProto->phone->createGroupCall(peer: $channel, title: $title);
$phone_GroupCallStreamRtmpUrl = $MadelineProto->phone->getGroupCallStreamRtmpUrl(peer: $channel, revoke: 1 );
$url = $phone_GroupCallStreamRtmpUrl['url'];
$key = $phone_GroupCallStreamRtmpUrl['key'];
Perhaps something needs to be specified in the ffmpeg values. Tell me please
I need to build a cgi file on a server. Compiling a simple test c++ file is working ok. The problem is I can not get get any build output, neither on success or failure.
<?php
header("Content-Type: text/plain");
$input = "test.c";
$output = "test.cgi";
//$cmd = "g++ --version";
$cmd = "g++ -g -Wall -O $input -o $output";
$retval = 0;
$errors = [];
exec($cmd, $errors, $retval);
foreach ($errors as $key => $line)
{
echo "$key $line" . PHP_EOL;
}
echo (intval($retval) ? "ERROR" : "OK") . PHP_EOL;
?>
when I run "g++ --version" I do get output, but not when compiling.
The G++ version is from 2015
Try redirecting the error output to the standard output with 2>&1:
$cmd = "g++ -g -Wall -O $input -o $output 2>&1";
You can also get the output as a string from exec() or shell_exec() by doing:
$output_message = exec($cmd, $errors, $retval);
I have two ways without success and different results, with exec method the ffmpeg actually works and creates the output file but then the website crashes with error 500.
if I use the proc_open method then it runs and creates the log file atest.log in the output store folder, but ffmpeg errors at the end with: store\audio_recording_1441120844021u.mp3: Permission denied and doesn't write the file out.
ffmpeg has IUSR full control permissions and those permissions are also on the store folder.
any ideas???
exec method:-
$cmd = "ffmpeg.exe -i C:\\Windows\\Temp\\recordings\\".$filename." -i watermark.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 store\\".$filename;
echo exec($cmd, $o, $v);
proc_open method:-
$cmd = "ffmpeg.exe -i C:\\Windows\\Temp\\recordings\\".$filename." -i watermark.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 store\\".$filename;
$pipes = array();
$descriptors = array(2 => array('file', 'store\\atest.log', 'a'));
$p = proc_open($cmd, $descriptors, $pipes);
$done = 0;
while (!$done)
{
sleep(1);
$status = proc_get_status($p);
if (!$status['running']) $done = 1;
echo "STEEL RUN\n";
// some manipulations with "store\\atest.log"
}
For the exec() function, adding -nostdin to the FFMPEG command did the trick:
$cmd = "ffmpeg.exe -nostdin -i C:\\Windows\\Temp\\recordings\\".$filename." -i watermark.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 store\\".$filename;
i host my phpvibe website on 247host, When i upload everything works fine except two things. When i am uploading videos then thumbnail is not generating and total time of video is not generating. When i contact their customer support they send me screen shot of terminal in which root executing my command and thumbnail is generated. but when i am doing this in vibecron.php then its not working. I purchased shared hosting, I dont have access to apache log, Now i am not able to understand why my script not working on server? and how i can test.
Here is my vibecron.php
<?php error_reporting(E_ALL);
//Vital file include
require_once("load.php");
$tp = ABSPATH.'/'.get_option('tmp-folder','rawmedia')."/";
$fp = ABSPATH.'/'.get_option('mediafolder')."/";
$ip = ABSPATH.'/'.get_option('mediafolder').'/thumbs/'; ;
//Run conversions
$crons = $db->get_results("select id,tmp_source,token from ".DB_PREFIX."videos where tmp_source != '' and source = '' limit 0,100000");
if($crons) {
foreach ($crons as $cron) {
$db->query("UPDATE ".DB_PREFIX."videos SET tmp_source='' WHERE id = '".intval($cron->id)."'");
$output ="{ffmpeg-cmd} -i {input} -vcodec libx264 -s {ffmpeg-vsize} -threads 4 -movflags faststart {output}.mp4";
//$output ="{ffmpeg-cmd} -i {input} -vcodec libx264 -s {ffmpeg-vsize} -threads 4 -strict experimental {output}.mp4";
$input = $tp.$cron->tmp_source;
$final = $fp.$cron->token;
$check = $fp.$cron->token.'.mp4';
$source= 'localfile/'.$cron->token.'.mp4';
if (file_exists($input)) {
//Start video conversion
$out = str_replace(array('{ffmpeg-cmd}','{input}','{ffmpeg-vsize}','{ffmpeg-bitrate}','{output}'),array(get_option('ffmpeg-cmd','ffmpeg'), $input, get_option('ffmpeg-vsize','640x360'), get_option('ffmpeg-bitrate','1750'),$final), $output);
shell_exec($out);
//Extract thumbnail
$imgout = "{ffmpeg-cmd} -itsoffset -4 -i {input} -y -f image2 -ss ".get_option('ffmpeg-thumb-time','00:00:03')." -vcodec mjpeg -vframes 1 -an -f rawvideo -s 500x300 {output}";
$imgfinal = $ip.$cron->token.'.jpg';
$thumb = str_replace(ABSPATH.'/' ,'',$ip.$cron->token.'.jpg');
$imgout = str_replace(array('{ffmpeg-cmd}','{input}','{output}'),array(get_option('ffmpeg-cmd','ffmpeg'), $input,$imgfinal), $imgout);
exec ( $imgout);
// Update so far
$db->query("UPDATE ".DB_PREFIX."videos SET thumb='".$thumb."', source='".$source."', pub = '".intval(get_option('videos-initial'))."' WHERE id = '".intval($cron->id)."'");
//Extract Duration
$cmd = get_option('ffmpeg-cmd','ffmpeg')." -i ".$check;
exec ( "$cmd 2>&1", $output );
$text = implode ( "\r", $output );
if (preg_match ( '!Duration: ([0-9:.]*)[, ]!', $text, $matches )) {
list ( $v_hours, $v_minutes, $v_seconds ) = explode ( ":", $matches [1] );
// duration in time format
$d = $v_hours * 3600 + $v_minutes * 60 + $v_seconds;
}
if(isset($d)) {
list ( $duration, $trash ) = explode ( ".", $d );
}
if(isset($duration)) {
$db->query("UPDATE ".DB_PREFIX."videos SET duration='".$duration."' WHERE id = '".intval($cron->id)."'");
}
add_activity('4', $cron->id);
/* End this loops item */
}
}
$db->clean_cache();
}
?>
They have a tester under "Requirements", and that's the first thing you should read when buying a script.
Make sure your ffmpeg works and your paths to ffmpeg in the cms and also that the ffmpeg version on server is right, they support 1.0+.
That php you've posted works fine for them, it's the config in the admin or the ffmpeg on your server the issue.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Run a ffmpeg process in the background
I was wondering if there's any easy way to runn and ffmpeg process in the background so people can leave the page. And if you do that, then tell if the ffmpeg process is running, and when it's done, update the database to "finished". I'll post my code if I need to. Thanks!
Here's the code on the processing page:
<?php
$name = $_FILES['upload_file']['name'];
$type = $_FILES['upload_file']['type'];
$size = $_FILES['upload_file']['size'];
$tmpname = $_FILES['upload_file']['tmp_name'];
if (!$title) {
$title = $name;
}
if (!$description) {
$description = "No description available.";
}
$string = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',10)),0,10);
$videoname = "$string.mp4";
$date = date("F d, Y"); // October 09, 2010
$srcFile = $tmpname;
mkdir("users/$usercode/uploads/$string");
mkdir("users/$usercode/uploads/$string/HD");
mkdir("users/$usercode/uploads/$string/regular");
mkdir("users/$usercode/uploads/$string/mobile_upload");
mkdir("users/$usercode/uploads/$string/thumbnails");
$destFile1 = "/users/$usercode/uploads/$string/HD/$string.mp4";
$destFile2 = "/users/$usercode/uploads/$string/regular/$string.mp4";
$destFile3 = "/users/$usercode/uploads/$string/mobile_upload/$string.mp4";
$ffmpegPath = "/usr/local/bin/ffmpeg";
$flvtool2Path = "/usr/bin/flvtool2";
$yamdiPath = "/usr/bin/yamdi";
$mp4boxPath = "/usr/local/bin/MP4Box";
// Create our FFMPEG-PHP class
$ffmpegObj = new ffmpeg_movie($srcFile);
// Save our needed variables
$srcWidth = $ffmpegObj->getFrameWidth();
$srcHeight = $ffmpegObj->getFrameHeight();
$srcFPS = $ffmpegObj->getFrameRate();
$srcAB = $ffmpegObj->getAudioBitRate();
$srcAR = $ffmpegObj->getAudioSampleRate();
$res = $srcWidth . "x" . $srcHeight;
// Call our convert using exec()
$iphone1 = getcwd().$destFile1;
$iphone2 = getcwd().$destFile2;
$iphone3 = getcwd().$destFile3;
$low = "854x480";
$local_img = "/users/$usercode/uploads/$string/thumbnails/$string.jpg";
$img = getcwd().$local_img;
$img = preg_replace('/ /','\ ',$img);
$thumb = "$string.jpg";
$cmd = "$ffmpegPath -i $tmpname 2>&1";
if (preg_match('/Duration: ((\d+):(\d+):(\d+))/s', `$cmd`, $time)) {
$total = ($time[2] * 3600) + ($time[3] * 60) + $time[4];
$interval = rand(0, $total);
}
$img = shell_exec("$ffmpegPath -ss $interval -i $tmpname 2>&1 -s 120x90 -f mjpeg -vframes 1 $img");
if ($srcWidth >= 1280 && $srcHeight >= 720) {
$out1 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre normal -ab $srcAB -ar $srcAR -b 5000k -r $srcFPS -s $res -acodec libfaac $iphone1");
$out2 = shell_exec("$mp4boxPath -inter 0.5 $iphone1");
$out3 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre normal -ab $srcAB -ar $srcAR -b 2000k -r $srcFPS -s $low -acodec libfaac $iphone2");
$out4 = shell_exec("$mp4boxPath -inter 0.5 $iphone2");
$out5 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre slow -ab 64k -ar 44100 -b 500k -r 30 -s $low -acodec libfaac $iphone3");
$out6 = shell_exec("$mp4boxPath -inter 0.5 $iphone3");
echo 1;
}
else {
$out3 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre normal -ab 64k -ar 44100 -b 500k -r 30 -s $low -acodec libfaac $iphone2");
$out4 = shell_exec("$mp4boxPath -inter 0.5 $iphone2");
$out5 = shell_exec("$ffmpegPath -i $tmpname -f mp4 -vcodec libx264 -vpre slow -ab 64k -ar 44100 -b 500k -r 30 -s $low -acodec libfaac $iphone3");
$out6 = shell_exec("$mp4boxPath -inter 0.5 $iphone3");
echo 1;
}
function generate_random($number_of_characters)
{
$characters = array();
$randomchar = "";
$x = 0;
for($i = 48; $i < 123; $i++)
{
if(ctype_alnum(chr($i)))
{
$characters[$x] = chr($i);
$x++;
}
}
for($i = 0; $i < $number_of_characters; $i++)
{
$randomchar .= $characters[rand(0, count($characters) - 1)];
}
return $randomchar;
}
?>
First of all, your code is very subject to SQL injection attacks and shell argument attacks. You need to escape all of your input to SQL and the shell commands!
I think this would be a standard approach to solving this problem:
Write your ffmpeg "job" to a database tuple. Note the job number, which would be the tuple's primary key. At this time the "status" needs to be something other than "complete."
Move all of your ffmpeg processing code to a helper PHP script. By helper, I simply mean another script. Call it something like "ffmpeg_job_processor.php".
Run that script in the background with a call to exec('php ffmpeg_job_processor.php '.escapeshellarg($jobNumber).' > /dev/null &'); The script will load the job from the database by ID, do all the processing, and when it's done it will update the database to "complete."
A web-based job monitor page could easily display the job status by looking up the same tuple by ID.
The trick is executing the second PHP script in the background so it will release your calling PHP script to continue on without blocking. You'll have to pipe your stdout to /dev/null (Linux box) and using the backgrounding operator &.
Some more good information is here: Run a ffmpeg process in the background