GoFuckYourself.com - Adult Webmaster Forum

GoFuckYourself.com - Adult Webmaster Forum (https://gfy.com/index.php)
-   Fucking Around & Business Discussion (https://gfy.com/forumdisplay.php?f=26)
-   -   Tech FFmpeg duration (https://gfy.com/showthread.php?t=1282613)

mikeworks 10-24-2017 11:27 AM

FFmpeg duration
 
I can see video duration with following command

Code:

ffmpeg -i 'video.mp4'

Duration: 00:01:17.92, start: 0.023220, bitrate: 1593 kb/s

Is there a way to use that duration value in the ffmpeg command?

Colmike9 10-24-2017 12:09 PM

PHP


$file=file.avi;
$time = exec("$ffmpeg -i /path/".$file." 2>&1 |
grep Duration | cut -d ' ' -f 4 | sed s/,//");
echo $time;

Barry-xlovecam 10-24-2017 12:45 PM

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:
sudo apt install libav-tools


...pvid/porno$ avconv -i \
Wife_sharing_her_husband_with_horny_lesbian_friend_Video.flv\
  2>&1 | grep Duration | sed 's/Duration: \(.*\), start.*/\1/g'

  00:39:16.04


mikeworks 10-25-2017 01:36 PM

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}

/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

Note the line break between the ffprobe and ffmpeg commands.

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
Without the line break, command line reports this error:

Syntax error: "(" unexpected

Is there any way to save into the database and maintain the important line break between the ffprobe and ffmpeg command?

Colmike9 10-25-2017 02:16 PM

Quote:

Originally Posted by Barry-xlovecam (Post 22048513)
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:
sudo apt install libav-tools


...pvid/porno$ avconv -i \
Wife_sharing_her_husband_with_horny_lesbian_friend_Video.flv\
  2>&1 | grep Duration | sed 's/Duration: \(.*\), start.*/\1/g'

  00:39:16.04


Yeah, I think I read it wrong before.. :upsidedow

Barry-xlovecam 10-25-2017 04:46 PM

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

mikeworks 10-26-2017 04:08 AM

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.

Barry-xlovecam 10-26-2017 05:26 AM

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?

mikeworks 10-26-2017 05:45 AM

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.

Barry-xlovecam 10-26-2017 06:35 AM

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).
  1. You need to loop a list of the files to process in a script. Then foreach($file){
  2. perform the commands (ffmpeg +)
  3. then get the duration 00:00:00
  4. do your database UPDATE }
  5. then in your cms get that duration value and display the HTML

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

mikeworks 10-26-2017 12:11 PM

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.

Kafka 10-26-2017 02:47 PM

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.

Barry-xlovecam 10-26-2017 03:08 PM

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?

symtab 10-27-2017 12:17 AM

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);
$json = json_decode(implode('', $output));
$duration = $json->format->duration;

Now in your watermark cmd you replace the duration with the above $duration variable.

Barry-xlovecam 10-27-2017 01:05 AM

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:

up vote
-1
down vote


This bash command works like a charm:

Code:

avconv -i 'in.mpg' -vcodec mjpeg -vframes 1 -an -f rawvideo \
-s 420x300 -ss `avconv -i in.mpg 2>&1 | grep Duration \
| awk '{print $2}' | tr -d , \
| awk -F ':' '{print ($3+$2*60+$1*3600)/2}'` out.jpg

shareimprove this answer

edited May 15 '15 at 7:40
Matt Joiner
463725

answered Nov 9 '14 at 17:14
Георги Стефанов
1



My god that's complicated ? Sridhar-Sarnobat Mar 18 '15 at 18:22
Last post -- well life ain't simple dude :)
awk -F ':' '{print ($3+$2*60+$1*3600)/2 gets your midpoint

mikeworks 10-27-2017 06:03 AM

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.

symtab 10-27-2017 07:29 AM

What i wrote is ment to be used from php. Is your script a shell script or you execute the cmd from php?

Barry-xlovecam 10-27-2017 08:01 AM

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
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




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 {}

mikeworks 10-27-2017 10:27 AM

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

symtab 10-27-2017 10:44 AM

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...

Barry-xlovecam 10-27-2017 10:55 AM

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*"
Make a .csv of that output
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
^^ works well in .sh (bash) scripts (cli) we are doing system work with ffmpeg. Use the right tool for the job rather than spend lots of time making what you know best work.

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 10:29 PM.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
©2000-, AI Media Network Inc