FFmpeg INTEL QuickSync VAAPI FAILURE [unknown libva error] - php

I have problems with FFmpeg and Intel QuickSync. If I start my ffmpeg command from shell it works correctly. But if I want to start the same ffmpeg command from an cronjob I get Failure with quicksync
My command is:
/bin/ffmpeg -vsync passthrough -copytb 1 -hwaccel qsv -probesize 5000000 -analyzeduration 16000000 -c:v hevc_qsv -recv_buffer_size 67108864 -i source -filter_complex "[v:0]hwdownload,format=pix_fmts=nv12[format:0]; [format:0]cvdelogo=filename=file:buffer_queue_size=150:detect_interval=25:score_min=0.4:scale_min=0.75:scale_max=1.25:padding_left=10:padding_right=10:padding_top=10:padding_bottom=10[cvdelogo]; [cvdelogo]split=outputs=1[hwupload:0]; [hwupload:0]hwupload=extra_hw_frames=10[map:v:0]" -map [map:v:0] -c:v h264_qsv -flags:v +global_header+cgop -preset:v veryfast -g 250 -b:v:0 6200k -maxrate:v:0 6200k -bufsize:v:0 6200k -map a:0 -c:a copy -f hls -hls_flags delete_segments -hls_time 10 -hls_list_size 6 output.m3u8
If I run that on terminal everything works. But if I want to start it from php with shell_exec command over an cronjob I get this failure:
[AVHWDeviceContext # 0x2cc7b80] Failed to initialise VAAPI connection: -1 (unknown libva error). Error creating a QSV device
I don't know why FFmpeg is not founding the vaapi device from cronjob, pls help me out of this issue.
Thanks

Related

Running PHP remotely via SSH

I have a video encoding server set up on Laravel Forge with nginx. I'm trying to run a testing script to encode a video remotely via SSH, using the LaravelCollective SSH package.
This is my testing script (index.php)
<?php
exec("ffmpeg -I input.mpg -c:v libx264 -preset faster -crf 22 -c:a aac -strict experimental -movflags +faststart -vf scale=360:-1 output.mp4 1> output.txt 2>&1");
When I SSH into the server and run the script from the command line it works: the video is encoded; the script is working.
$ php /home/forge/mydomainname.com/public/test/index.php
However, when I run the same command locally in my Laravel app - using the SSH package - it doesn't encode and I receive no output; the browser just returns a white page.
SSH::run('php /home/forge/mydomainname.com/public/test/index.php', function($line) {
echo $line.PHP_EOL;
});
However however, if I open index.php, comment out the FFmpeg command and add some code to check if exec is enabled, it will execute and send output, so I know that the SSH package is actually working and executing the script remotely.
<?php
// exec("ffmpeg -I input.mpg -c:v libx264 -preset faster -crf 22 -c:a aac -strict experimental -movflags +faststart -vf scale=360:-1 output.mp4 1> output.txt 2>&1");
if(function_exists('exec')) {
echo "exec is enabled";
} else {
echo "exec is disabled";
}
It will return "exec is enabled" to my browser.
To sum up:
The script will encode video when running it via the command line on the server.
The script will not encode video when running it remotely.
The script will execute when running it remotely.
WTH?
I figured it out.
From within my Laravel app I decided to try echo exec('whoami'); and see if that returned anything to the browser. It did, so I knew exec() was working and I could trigger it via the SSH package.
Then I realized that my ffmpeg encoding command was suppressing output with 2>&1. I removed that and finally saw what was going on: I was receiving a "file not found" error, which was weird because input.mpg is in the same directory as index.php.
This has worked on three other servers, but not on this one created with Forge.
So I added the full path to the input file and voilĂ ! It works!
exec("ffmpeg -i /home/forge/mydomainname.com/public/test/input.mpg -c:v libx264 -preset faster -crf 22 -c:a aac -strict experimental -movflags +faststart -vf scale=360:-1 /home/forge/mydomainname.com/public/test/output.mp4 1> /home/forge/mydomainname.com/public/test/output.txt ");

PHP ffmpeg from command line

When i run the ffmpeg command directly in the command line it is working. But when i used the php command is breaking and getting error (At least one output file must be specified)
Code directly in command line
ffmpeg -i "F:/Sites/raaga_deploy36/mp4/arul/ghajini_rahath-96.mp4" -y -c copy -bsf h264_mp4toannexb -flags global_header -map 0 -f segment -segment_time 10 -segment_list "F:/Sites/raaga_deploy36/mp4/m3u8/ghajini_rahath-96.m3u8" -segment_format mpegts "F:/Sites/raaga_deploy36/mp4/m3u8/ghajini_rahath-96-segment_%05d.ts"
Code from PHP
$mfile=escapeshellarg($dir.$file);
$cfile=escapeshellarg($dir1.$fname.".m3u8");
$cfile_sg=escapeshellarg($dir1.$fname."-segment_%05d.ts");
$cmd="ffmpeg -i ".$mfile."-y -c copy -bsf h264_mp4toannexb -flags global_header -map 0 -f segment -segment_time 10 -segment_list ".$cfile.".m3u8 -segment_format mpegts ".$cfile_sg;
$res=shell_exec( $cmd );
Output in the command line
ffmpeg -i "C:/sites/hls/mp4/arul/ghajini_orum-128.mp4
"-y -c copy -bsf h264_mp4toannexb -flags global_header -map 0 -f segment -segmen
t_time 10 -segment_list "C:/sites/hls/mp4/m3u8/ghajini_orum-128.m3u8".m3u8 -segm
ent_format mpegts "C:/sites/hls/mp4/m3u8/ghajini_orum-128-segment_ 05d.ts"
since the commands (line) are breaking here it is not working.
please see the link below
http://dv.raaga.com/new_ig/m3u_convert_err.jpg
Thanks
Thanigaivelan

How to programmatically start/stop FFMPEG stream transcoding

I have an ip webcam which provides an MJPEG stream. I can successfully transcode and save that stream with ffmpeg under OSX. The following gives me pretty much what I want:
ffmpeg -f mjpeg -i "http://user:pass#10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4
That will start an FFMPEG session and begin saving the live stream to my test.mp4 file. pressing q will quit ffmpeg and save the file.
I would like to programmatically start & stop the recording using a PHP or Bash shell script. I have tried the following:
<?php
$pid = pcntl_fork();
if($pid == -1){
die("could not fork");
}elseif($pid){
// we are the parent...
print $pid.' started recording. waiting 10 seconds...';
sleep(10); // Wait 10 seconds
print_r(shell_exec("kill ".$pid)); // Kill the child recording process
echo 'done';
exit();
}else{
// we are the child process. call ffmpeg.
exec('../lib/ffmpeg -f mjpeg -i "http://user:pass#10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4');
}
But there are two problems:
The ffmpeg process does not end/die (probably because its forked again)
When I manually kill the ffmpeg process, the video file is not readable
So I was doing a combination of things wrong.
For starters, I needed to push the output form ffmpeg to a log file and also tell it to overwrite my temp file without prompting using the -y argument.
So instead of
ffmpeg -f mjpeg -i "http://user:pass#10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4
I am now using
ffmpeg -y -f mjpeg -i "http://user:pass#10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4 </dev/null >/dev/null 2>/tmp/ffmpeg.log &
The second problem was that I wasn't waiting long enough before sending the kill command to ffmpeg, and so a corrupt file was being created.
By adding the -t (for time limit) argument with 1 second, I determined that it takes an average of 15 seconds for ffmpeg to record 1 second of video. Increasing the time limit to 10 seconds made the average increase to 25 seconds, so it seems that on my server at least, theres 14 seconds of overhead. By increasing my sleep command in my php script to 30 seconds, I was able to get a useable video file.
So having PHP kill the ffmpeg process results in an unknown (or approximate at best) recording time length which is completely dependent on CPU power, network bandwidth, etc.
Thats a bit of a bummer because I had hoped to be able to increase the recording length depending on some external variables (I have insteon motion sensors feeding a database, i would like to record until the motion stops).
In any event, here is a working PHP script in case it helps someone in the future:
<?php
print date('H:i:s')."\nStarted recording. waiting 60 seconds...\n";
exec('../lib/ffmpeg -y -f mjpeg -i "http://user:pass#10.0.1.200/nphMotionJpeg?Resolution=640x480&Quality=Standard" -b:v 1500k -vcodec libx264 /tmp/test.mp4 </dev/null >/dev/null 2>/tmp/ffmpeg.log &');
sleep(60); // Wait long enough before killing, otherwise the video will be corrupt!
shell_exec('pkill ffmpeg'); // find and kill
echo "done\n\n";
exit();
?>
Send a SIGQUIT signal to the background process to terminate the ffmpeg command normally.
Just use
kill -s QUIT $PID
and the process will finish with a non-corrupted MP4 video file.
Send the "q" key:
process.StandardInput.WriteLine("q");

How to pipe a new command after ffmpeg background process completes?

This is my ffmpeg process:
exec("/usr/local/bin/ffmpeg -y -i source.avi dest.mp4 >/dev/null 2>/dev/null &
Now, I wish to execute a PHP file after the conversion is complete. Logically, this is what I have:
exec("/usr/local/bin/ffmpeg -y -i source.avi dest.mp4 >/dev/null 2>/dev/null ; php proceed.php &
This doesn't work though, since then PHP will hold up the process to wait till the ffmpeg conversion is complete. What I want is basically to call proceed.php after the conversion completes, both of which are done in the background.
If anyone can provide the Windows server solution, that will be awesome too.
Write an external (bash/php) script that executes both the ffmpeg and php process, and tack & after that.
For windows, please open a new question on SO.
To add on to what Evert had posted, here is an example of what I use for my FFMPEG bash script... it's far from done (it doesn't alert if the program crashes, for instance) but it's somewhere to start:
#!/bin/sh
## Set our paths
FFMPEG_PATH=/usr/local/bin
SITE_PATH=path_to_file
VIDEO_PATH=$SITE_PATH/public_html/videos
## Make sure we have permissions to do this stuff
chown -R wwwrun:www $VIDEO_PATH/$2
chmod -R 765 $VIDEO_PATH/$2
## Set the options for mp4 compression
options="-vcodec libx264 -b 512k -ar 22050 -flags +loop+mv4 -cmp 256 \
-partitions +parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 \
-me_method hex -subq 7 -trellis 1 -refs 5 -bf 3 \
-flags2 +bpyramid+wpred+mixed_refs+dct8x8 -coder 1 -me_range 16 \
-g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10\
-qmax 51 -qdiff 4"
## Start the conversion.
$FFMPEG_PATH/ffmpeg -y -i $VIDEO_PATH/$2/original/$1 -an -pass 1 -threads 2 $options $VIDEO_PATH/$2/$2.mp4 2> $VIDEO_PATH/$2/pass_one.log
$FFMPEG_PATH/ffmpeg -y -i $VIDEO_PATH/$2/original/$1 -acodec libfaac -ab 96k -pass 2 -threads 2 $options $VIDEO_PATH/$2/$2.mp4 2> $VIDEO_PATH/$2/pass_two.log
## Create the thumbnail for the video
. $SITE_PATH/bin/create_thumbnail $2 00:00:15 2> $VIDEO_PATH/$2/generate_thumbnails.log
## Clean up the log files that were created
## find /log_path/ -name *log* -exec rm {} \;
## Update datbase and send email that we're done here.
php $SITE_PATH/public_html/admin/includes/video_status.php converting_finished $2
And this all gets called from a PHP file that does (along with some other code):
proc_close(proc_open(server_path.'/bin/convert_video_mp4 '.mysql_result($next_video, 0, "uid").'.'.mysql_result($next_video, 0, "original_ext").' '.mysql_result($next_video, 0, "uid").' &', array(), $foo));
PS - I know mysql extension are on their way out, I haven't been using or updating this code in a while, so please update to your specifications

Recording audio with FFMPEG works in terminal but not through exec() of PHP

I use this command to RECORD audio and video from my webcam in terminal and it works!
ffmpeg -f video4linux2 -r 25 -sameq -s 640x480 -i /dev/video0 -f alsa -i plughw:0,0 -ar 22050 -ab 128k -y webcam.flv
But when I do it through PHP, like this:
echo shell_exec('ffmpeg -f video4linux2 -r 25 -sameq -s 640x480 -i /dev/video0 -f alsa -i plughw:0,0 -ar 22050 -ab 128k -y webcam.flv 2>&1 &');
I receive that log:
ffmpeg version 0.8.6-4:0.8.6-0ubuntu0.12.04.1, Copyright (c) 2000-2013 the Libav developers built on Apr 2 2013 17:02:36 with gcc 4.6.3 * THIS PROGRAM IS DEPRECATED * This program is only provided for compatibility and will be removed in a future release. Please use avconv instead. [video4linux2 # 0x23579a0] Estimating duration from bitrate, this may be inaccurate Input #0, video4linux2, from '/dev/video0': Duration: N/A, start: 4868.729067, bitrate: 122880 kb/s Stream #0.0: Video: rawvideo, yuyv422, 640x480, 122880 kb/s, 25 tbr, 1000k tbn, 25 tbc Home directory /var/www not ours.
ALSA lib pcm_hw.c:1401:(_snd_pcm_hw_open) Invalid value for card [alsa # 0x23589e0] cannot open audio device plughw:0,0 (No such file or directory) plughw:0,0: Input/output error
Before I got that Mic device problem I was having problem with the Webcam device's permissions, then i did:
sudo chmod -R 777 /dev/video0
And the video capture was ready to be used! But now I got this Mic device problem!
I think it can be about permissions too, but I dont know linux very well and have no idea how to fix that!
Thanks!
I just found the solution! =x
sudo chmod -R 666 /dev/snd/*

Categories