![]() |
FFmpeg duration
I can see video duration with following command
Code:
ffmpeg -i 'video.mp4' |
PHP
$file=file.avi; $time = exec("$ffmpeg -i /path/".$file." 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//"); echo $time; |
https://stackoverflow.com/questions/...-ffmpeg-output
here are some interesting ideas to try -- you don't need php Code:
The program 'avconv' is currently not installed. You can install it by typing: |
Thanks guys, with current encoded script I have found another solution that almost works.
If I paste this into command line it works: Code:
eval $(ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=duration /path/to/file/1.mp4) duration=${streams_stream_0_duration} Now, when I save this in the database of encoded script (only way to use command), it removes that line ending up like this: Code:
eval $(ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=duration /path/to/file/1.mp4) duration=${streams_stream_0_duration} /usr/local/bin/ffmpeg -i '/path/to/file/1.mp4' -vf 'scale=448:trunc(ow/a/vsub)*vsub' -vf drawtext="fontsize=16:[email protected]:fontfile=/usr/local/share/fonts/freefont-ttf/FreeSans.ttf:text='Blah blah blah':y=25:x=w-(t-($duration/2))*w/20" -threads 0 -acodec libfaac -ar 44100 -ab 128k -vcodec libx264 -preset slower -keyint_min 25 -g 250 -r 25 -y /path/to/output/file/temp_vid.mp4 Syntax error: "(" unexpected Is there any way to save into the database and maintain the important line break between the ffprobe and ffmpeg command? |
Quote:
|
try
${streams_stream_0_duration} /usr/local/b replaced with ${streams_stream_0_duration}; /usr/local/b or ${streams_stream_0_duration} && /usr/local/b if that won't work you will need to run it as 2 commands in a bash *.sh script loop and read `cat`a file list |
Thanks for help. I have tried everything so far and still no joy.
I went from using ffprobe to ffmpeg itself to output duration in seconds: duration=$(/usr/local/bin/ffmpeg -i /path/to/file/1.mp4 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@\..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }') /usr/local/bin/ffmpeg -i /path/to/file/1.mp4 -vf 'scale=448:trunc(ow/a/vsub)*vsub' -vf drawtext="fontsize=16:[email protected]:fontfile =/usr/local/share/fonts/freefont-ttf/FreeSans.ttf:text='Blah blah blah':y=25:x=w-(t-($duration/2))*w/20" -threads 0 -acodec libfaac -ar 44100 -ab 128k -vcodec libx264 -preset slower -keyint_min 25 -g 250 -r 24 -y /path/to/output/temp_vid.mp4 It works in command line perfect, even without a line break it works. But when I save it in database for script to use, damn thing won't encode and shows in admin area the error code, if I copy the 'error code' into command line it works perfect. |
what is it?
"But when I save it in database" what gets stored in the 'database'( mysql? ) paste me/us the stored field value and the table column type you are storing it in? a ':' is not the same in all column types https://dev.mysql.com/doc/refman/5.7/en/time.html you are not dealing with time you are dealing with text you are not performing time arithmetic (end time - start time)=elapsed time you are just trying to store and retrive a text value of 'video run time length' Is this the problem? |
The field value is:
duration=$(%ffmpeg_path% -i %video_file% 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }') %ffmpeg_path% -i %video_file% %video_filters% -vf 'scale=448:trunc(ow/a/vsub)*vsub' -vf drawtext="fontsize=16:[email protected]:fontfile =/usr/local/share/fonts/freefont-ttf/FreeSans.ttf:text='Blah blah blah':y=25:x=w-(t-($duration/2))*w/20" -threads 0 %audio_encoder% -ar 44100 -ab %audio_bitrate%k -vcodec libx264 -preset slower -keyint_min 25 -g 250 -r %video_fps% %video_rotate% -y %video_target% The field type is 'text'. You can see the script replaces %ffmpeg_path% and others with true values. I need to determine the duration of the video in seconds. Then divide that duration by 2, so I can add a watermark half way through the video. |
The field value in your database server should be the result like 45:09:32 or similar. The returned result of your command.
I would use a bash .sh script for this. You can use PHP, Python, or other interrupter language you would prefer also (the devil you know best).
MyVideo elapsed time 45:09:32 That is what you want to do? NO i read it again LOL you need to do this in a few processes. convert the video. determine the seconds like 2400 the do the math 1200 = the middle convert that to time 00:20:00 and use that in the command (a separate command to watermark) nope :( edited -- that didn't work right you are going to have to do a script for the math ... but that is the logic to use |
The database field runtime contains the count in seconds for example 256, but only after the video has been processed. Would then have to process video a second time to add watermark.
This is not ideal solution due to content amount and that cdn will sync video as soon as it has been encoded, and won't unless manual flush via contacting host, sync video after second encoding. It's frustrating. I have no idea why the exact same code pasted into command line works, but script fails when using it. The ffmpeg log is showing this: [Parsed_drawtext_0 @ 0x808c3e320] [Eval @ 0x7fffffff9250] Undefined constant or missing '(' in '/2))*w/20' [Parsed_drawtext_0 @ 0x808c3e320] Failed to configure input pad on Parsed_drawtext_0 Error opening filters! So it looks like when run via script $duration is empty. |
You can add a linebreak : \n
Or just type a linebreak in the mysql insert like: this is a linebreak Or make one line by adding a && between the commands. |
Use a bash script loop the files and ladder though it echoing out the variables. That is how you want to run terminal commands.
$ ./watermark.sh Is that what you are doing? |
You can use ffprobe to actually get a json string. You can then convert this json string to an object in php with json_decode. This is more elegant and simplier.
Code:
exec('ffprobe -v quiet -loglevel quiet -show_format -show_streams -print_format json file.mp4', $output); |
I found this It maybe could be adapted
the purpose was to extract a thumbnail from the middle but it does find the middle an do something your problem is that you want to do this in a single pass the thread> https://superuser.com/questions/4773...eo-with-ffmpeg Quote:
awk -F ':' '{print ($3+$2*60+$1*3600)/2 gets your midpoint |
Thanks everyone for help.
Problem is made much more difficult due to script being encoded. I tried this as suggested: exec('ffprobe -v quiet -loglevel quiet -show_format -show_streams -print_format json %video_file%', $output); $json = json_decode(implode('', $output)); $duration = $json->format->duration; $duration = $duration/2; But whenever I have tried ffprobe it breaks the scripts encoding process for whatever reason. In command line it works perfect. This works: duration=$(%ffmpeg_path% -i %video_file% 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }') ; %ffmpeg_path% -i %video_file% %video_filters% -vf 'scale=448:trunc(ow/a/vsub)*vsub' -vf drawtext="fontsize=16:[email protected]:fontfile =/usr/local/share/fonts/freefont-ttf/FreeSans.ttf:text='Blah blah blah':y=25:x=w-(t-($duration/2))*w/20" -threads 0 %audio_encoder% -ar 44100 -ab %audio_bitrate%k -vcodec libx264 -preset slower -keyint_min 25 -g 250 -r %video_fps% %video_rotate% -y %video_target% as does this: duration=$(%ffmpeg_path% -i %video_file% 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }') && %ffmpeg_path% -i %video_file% %video_filters% -vf 'scale=448:trunc(ow/a/vsub)*vsub' -vf drawtext="fontsize=16:[email protected]:fontfile =/usr/local/share/fonts/freefont-ttf/FreeSans.ttf:text='Blah blah blah':y=25:x=w-(t-($duration/2))*w/20" -threads 0 %audio_encoder% -ar 44100 -ab %audio_bitrate%k -vcodec libx264 -preset slower -keyint_min 25 -g 250 -r %video_fps% %video_rotate% -y %video_target% and this: duration=$(%ffmpeg_path% -i %video_file% 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print (3600*A[1] + 60*A[2] + B[1])/2 }') && %ffmpeg_path% -i %video_file% %video_filters% -vf 'scale=448:trunc(ow/a/vsub)*vsub' -vf drawtext="fontsize=16:[email protected]:fontfile =/usr/local/share/fonts/freefont-ttf/FreeSans.ttf:text='Blah blah blah':y=25:x=w-(t-($duration))*w/20" -threads 0 %audio_encoder% -ar 44100 -ab %audio_bitrate%k -vcodec libx264 -preset slower -keyint_min 25 -g 250 -r %video_fps% %video_rotate% -y %video_target% As in it actually create thumbs, encodes video, watermarks video. But, the watermark appears from the start of the video. So I guess the $duration is not being populated with a value. I have a log being generated now by ffmpeg by adding 2> 'path/to/log.txt' at the end of the command. It would helpful if it showed the ffmpeg command executed, but it only shows the encoding process. I believe I can adjust log to debug level, so will try that next, in case it gives a clue why $duration empty. |
What i wrote is ment to be used from php. Is your script a shell script or you execute the cmd from php?
|
duration=$(%ffmpeg_path% -i %video_file% 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@..*@@g' | awk '{ split($1, A, ":")}'
#; split(A[3], B, ".") echo $duration ; is an end next; next ... This really needs to be in a bash script --then you don't need all the ;'s and it is a lot less confusing to work with IMO Code:
#!/bin/bash see if it works now Ladder up with the rest of the code spaghetti is good for dinner -- that is one fuck of a one liner (I like :) ) but can get confusing. gedit has a plugin that matches brackets {} |
Script is php with database. The ffmpeg code is saved to field in database. Then script executes that code.
With debug ffmpeg I can see problem is with variable duration: Reading option '-vf' ... matched as option 'vf' (set video filters) with argument 'drawtext=fontsize=16:[email protected]:fontfile =/usr/local/share/fonts/freefont-ttf/FreeSans.ttf:text='Blah blah blah':y=25:x=w-(t-0)*w/20'. You can see t-0, where 0 should be the duration. duration=10 works duration=$(10) does not assign value to variable, 0 output as above duration="$(10)" does not assign value to variable, 0 output as above duration=`10` does not work, breaks encoding I will try and work out how to integrate bash solution, thanks. But difficult with encoded script knowing how to send value of %video_file% to a bash script. More head scratching to do. :arcadefre |
So what you could do is first get the duration and save it to a $duration variable. The ffmpeg command you use #DURATION# where you want to have the duration. Then you run str_replace like str_replace('#DURATION#', $duration, $ffmpeg_cmd); then you run the cmd. Also the ffmpeg drawtext requires to escape some characters, if you use single quote for the drawtext options then use double quote for the text itself (or remove the single quotes, this will also work), also other characters that need to be excaped are :,} and some other characters...
|
If you are working with a PHP Iron Cube or similar script encoding you are working with one hand tied behind your back.
I think you will need to do this in bash outside of your encoded script. Just work one level above your video directory(s) Code:
find . "*.mpg*" then loop the files in a bash variable do the commands. it is trivial to loop twice only the time to read and do the conversion. if you have to; make a second .csv with the filepath, time just cut -d',' -f? < assign the field variables then loop that file and watermark I guess. You don't need PHP to do this that is like pounding a nail with a pile driver. It will take 2 days to set up the pile driver then you will bend the nail. PHP is a interpreter language. As soon as you start doing system commands in PHP other than for something trivial you will make a mess. Code:
php script.php Oh, and PHP json_encode; _decode; is good for many things. I am using it a lot these days but for its intended purpose ... JSON Use the right tool ... |
All times are GMT -7. The time now is 04:24 AM. |
Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2025, vBulletin Solutions, Inc.
©2000-, AI Media Network Inc