I have tried extracting video.mpg to images using FFmpeg command line and it works fine, but I want get time of the conversion process that will be taken till video.mpg is extracted, and save to Time.txt.
This is what I have tried so far:
ffmpeg -i video.mpg image%d.jpg>>time.txt
Where I have been wrong?
ffmpeg outputs the progress messages to stderr, so to redirect it to a file use 2>>time.txt:
ffmpeg -i video.mpg image%d.jpg 2>>time.txt
More info: http://ss64.com/nt/syntax-redirection.html
P.S. in batch-files % should be doubled: ffmpeg -i video.mpg image%%d.jpg 2>>time.txt
Related
I have a bat file which runs the volumedetect filter:
ffmpeg -i C:\Users\Nate\Videos\VideoClips\1080p-47243316.mp4 -filter:a volumedetect -f null /dev/null
Is it possible to capture all this output text it sends to cmd, and manipulate it to the point of storing say, the mean_volume into a variable?
Volumedetect output example:
So easy and cool batch question. Sorry for this ultimate newbie question !
I've a folder which contains hundreds of videos like that:
Video001 - Introduction.avi
Video002 - History of Stack Overflow.avi
Video003 - Before Asking.avi
...
Video999 - Conclusion.avi
I need re-encode all of them with x264 codec. Ffmpeg is very slow so I tried to use HandBrake. There is a command line edition of HB and great default presents. I could write this command for converting only one file with "Normal" present:
HandBrakeCLI.exe -i "Video001 - Introduction.avi" -o "Video001 - Introduction.mp4" -Z Normal
My question: How can I convert all of them in folder and delete after conversion process? Thank you!
Note: If you think ffmpeg is better solution I can give my fav present. Handbrake says about Normal present:
Normal: -e x264 -q 20.0 -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 --loose-anamorphic --modulus 2 -m --x264-preset veryfast --h264-profile main --h264-level 4.0
for %%f in (*.avi) do (
handbrakecli.exe -i "%%~nxf" -o "%%~nf.mp4" -Z Normal
del "%%~f"
)
For each avi file, call handbrake with the name and extension of input file and generate an output file with the name of the original file and .mp4 extension
I'm using ffmpeg to extract the audio from different video formats (flv, mp4) and convert it to mp3.
%~dp0ffmpeg.exe -i %1 -ar 44100 -ac 2 -ab 128k "%~dpn1.mp3"
This works just fine. However, in my input files, the audio bitrate varies, and I want to adjust the output bitrate accordingly. Even by extensive Google searching, I didn't find any hint how to just keep the original bitrate.
What I would need would be something like:
-ab copy
Which, of course, does not work.
Is there anything that will work?
P.S: As you might have figured from the formatting above, I'm using a windows batch file. There would be the hack to use %~dp0ffmpeg.exe -i, get the audio bitrate by grep and insert it in the command line. I just think there has to be an easier and more elegant way.
even though the original thread was looking for an answer without grepping anything, nate's script seems to be the most useful post. but it has some limitations, for example not all outputs give you a bitrate grepped, some turnout to give you just the result "default". here's a little more improved version of it.
#!/bin/env bash
ext=$1
for f in *.${ext}; do
x=${f%.*} ;
x=${x% - YouTube}; # I usually download some song covers from YouTube.
x=$x".mp3";
bit=`ffmpeg -i "${f}" 2>&1 | grep Audio | awk -F", " '{print $5}' | cut -d' ' -f1`
if [ -n "$bit" ]; then
ffmpeg -i "$f" -ab ${bit}k "$x"
else
ffmpeg -i "$f" "$x" # this is if we don't have an output from the grep line above, ffmpeg will keep the original quality, that is 192k for 192k
fi
done
Here is a bash script that will take a file extension and extract audio from any file with that extension, and of course maintain the bitrate. I can't claim the credit of the key piece of the code, as that goes to the gentleman that writes this blog.
#!/bin/bash
ext=$1
for file in *.${ext}; do
tmpfn=${file%.*} ; # get rid of file ext
tmpfn=$tmpfn".mp3"; # add mp3 file ext
# next line gets bitrate of audio from video using ffmpeg
bit=`ffmpeg -i "${file}" 2>&1 | grep Audio | awk -F", " '{print $5}' | cut -d' ' -f1`
# finally, convert to mp3 using proper bitrate
ffmpeg -i "$file" -ab ${bit}k "$tmpfn"
done
Just run it in the directory where you have the files like so:
$bash script.sh flv
where flv is the file extension. Hack it to make it do exactly as you wish or process multiple filetypes to your heart's content.
EDIT: Just a quick note for anyone on Ubuntu/debian/etc. Make sure you install the additional codec package or else it won't work, i.e. you must install ffmpeg and the extra libav codec package or you're gonna have a bad time. This should do the trick:
sudo apt-get ffmpeg libavcodec-extra-53
As LordNeckbeard states, using the same bitrate to encode in different formats isn't necessarily wise. However...
Here is a batch-file solution which captures the input file bitrate and uses that as a parameter for the encoding command line. This approach was hinted at by the original questioner. The mp3 output file is created in the same folder as the input file.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
REM Usage: scriptname.cmd "full-quoted-path-to-input-file"
REM Adjust FFMPEG_PATH variable value to match the path to your FFMPEG binary
SET FFMPEG_PATH=C:\Program Files\ffmpeg-20170807-1bef008-win64-static\bin
SET INPUT_FILE_FULL_PATH=%1
REM Get input file bitrate
FOR /F "tokens=5 delims==," %%i IN ('""%FFMPEG_PATH%\ffmpeg.exe" -i %INPUT_FILE_FULL_PATH% 2>&1 | find "Audio:""') DO (
FOR /F "tokens=1 delims==k" %%j IN ('ECHO %%i') DO (
SET BITRATE=%%j
SET BITRATE=!BITRATE: =!
ECHO Input file bitrate is !BITRATE! kb/s
)
)
REM Encode file using previously captured bitrate
"%FFMPEG_PATH%\ffmpeg.exe" -i %INPUT_FILE_FULL_PATH% -ar 44100 -ac 2 -ab !BITRATE!k "%~dpn1.mp3"
There is scope for tightening the code up, for example, a check to make sure at least one argument was provided, and that the BITRATE is not empty before beginning the encode, but as a rough and ready solution this should do fine.
Current version of ffmpeg (tested 2.1.4) recommends using "-qscale 0" to preserve quality. This worked for me on my mpeg4 video test file.
Try this option: -codec copy or -acodec copy for only audio.
Check this reference http://ffmpeg.org/ffmpeg.html#Stream-specifiers-1
Instead of
-ab copy
try
-sameq
%~dp0ffmpeg.exe -i %1 -sameq "%~dpn1.mp3"
I want to be able to log FFMPEG processes because I am trying to work out how long a minute of video takes to convert to help with capacity planning of my video encoding server. How do I enable logging and where is the log file saved. I have FFMPEG installed on a CentOS LAMP machine.
FFmpeg does not write to a specific log file, but rather sends its output to standard error. To capture that, you need to either
capture and parse it as it is generated
redirect standard error to a file and read that afterward the process is finished
Example for std error redirection:
ffmpeg -i myinput.avi {a-bunch-of-important-params} out.flv 2> /path/to/out.txt
Once the process is done, you can inspect out.txt.
It's a bit trickier to do the first option, but it is possible. (I've done it myself. So have others. Have a look around SO and the net for details.)
I found the below stuff in ffmpeg Docs. Hope this helps! :)
Reference: http://ffmpeg.org/ffmpeg.html#toc-Generic-options
‘-report’ Dump full command line and console output to a file named
program-YYYYMMDD-HHMMSS.log in the current directory. This file can be
useful for bug reports. It also implies -loglevel verbose.
Note: setting the environment variable FFREPORT to any value has the
same effect.
I find the answer.
1/First put in the presets, i have this example "Output format MPEG2 DVD HQ"
-vcodec mpeg2video -vstats_file MFRfile.txt -r 29.97 -s 352x480 -aspect 4:3 -b 4000k -mbd rd -trellis -mv0 -cmp 2 -subcmp 2 -acodec mp2 -ab 192k -ar 48000 -ac 2
If you want a report includes the commands -vstats_file MFRfile.txt into the presets like the example. this can make a report which it's ubicadet in the folder source of your file Source.
you can put any name if you want , i solved my problem "i write many times in this forum" reading a complete .docx about mpeg properties. finally i can do my progress bar reading this txt file generated.
Regards.
ffmpeg logs to stderr, and can log to a file with a different log-level from stderr. The -report command-line option doesn't give you control of the log file name or the log level, so setting the environment variable is preferable.
(-v is a synonym for -loglevel. Run ffmpeg -v help to see the levels. Run ffmpeg -h full | less to see EVERYTHING. Or consult the online docs, or their wiki pages like the h.264 encode guide).
#!/bin/bash
of=out.mkv
FFREPORT="level=32:file=$of.log" ffmpeg -v verbose -i src.mp4 -c:a copy -preset slower -c:v libx264 -crf 21 "$of"
That will trancode src.mp4 with x264, and set the log level for stderr to "verbose", and the log level for out.mkv.log to "status".
(AV_LOG_WARNING=24, AV_LOG_INFO=32, AV_LOG_VERBOSE=40, etc.). Support for this was added 2 years ago, so you need a non-ancient version of ffmpeg. (Always a good idea anyway, for security / bugfixes and speedups)
A few codecs, like -c:v libx265, write directly to stderr instead of using ffmpeg's logging infrastructure. So their log messages don't end up in the report file. I assume this is a bug / TODO-list item.
To log stderr, while still seeing it in a terminal, you can use tee(1).
If you use a log level that includes status line updates (the default -v info, or higher), they will be included in the log file, separated with ^M (carriage return aka \r). There's no log level that includes encoder stats (like SSIM) but not status-line updates, so the best option is probably to filter that stream.
If don't want to filter (e.g. so the fps / bitrate at each status-update interval is there in the file), you can use less -r to pass them through directly to your terminal so you can view the files cleanly. If you have .enc logs from several encodes that you want to flip through, less -r ++G *.enc works great. (++G means start at the end of the file, for all files). With single-key key bindings like . and , for next file and previous file, you can flip through some log files very nicely. (the default bindings are :n and :p).
If you do want to filter, sed 's/.*\r//' works perfectly for ffmpeg output. (In the general case, you need something like vt100.py, but not for just carriage returns). There are (at least) two ways to do this with tee + sed: tee to /dev/tty and pipe tee's output into sed, or use a process substitution to tee into a pipe to sed.
# pass stdout and stderr through to the terminal,
## and log a filtered version to a file (with only the last status-line update).
of="$1-x265.mkv"
ffmpeg -v info -i "$1" -c:a copy -c:v libx265 ... "$of" |& # pipe stdout and stderr
tee /dev/tty | sed 's/.*\r//' >> "$of.enc"
## or with process substitution where tee's arg will be something like /dev/fd/123
ffmpeg -v info -i "$1" -c:a copy -c:v libx265 ... "$of" |&
tee >(sed 's/.*\r//' >> "$of.enc")
For testing a few different encode parameters, you can make a function like this one that I used recently to test some stuff. I had it all on one line so I could easily up-arrow and edit it, but I'll un-obfuscate it here. (That's why there are ;s at the end of each line)
ffenc-testclip(){
# v should be set by the caller, to a vertical resolution. We scale to WxH, where W is a multiple of 8 (-vf scale=-8:$v)
db=0; # convenient to use shell vars to encode settings that you want to include in the filename and the ffmpeg cmdline
of=25s#21.15.${v}p.x265$pre.mkv;
[[ -e "$of.enc" ]]&&echo "$of.enc exists"&&return; # early-out if the file exists
# encode 25 seconds starting at 21m15s (or the keyframe before that)
nice -14 ffmpeg -ss $((21*60+15)) -i src.mp4 -t 25 -map 0 -metadata title= -color_primaries bt709 -color_trc bt709 -colorspace bt709 -sws_flags lanczos+print_info -c:a copy -c:v libx265 -b:v 1500k -vf scale=-8:$v -preset $pre -ssim 1 -x265-params ssim=1:cu-stats=1:deblock=$db:aq-mode=1:lookahead-slices=0 "$of" |&
tee /dev/tty | sed 's/.*\r//' >> "$of.enc";
}
# and use it with nested loops like this.
for pre in fast slow; do for v in 360 480 648 792;do ffenc-testclip ;done;done
less -r ++G *.enc # -r is useful if you didn't use sed
Note that it tests for existence of the output video file to avoid spewing extra garbage into the log file if it already exists. Even so, I used and append (>>) redirect.
It would be "cleaner" to write a shell function that took args instead of looking at shell variables, but this was convenient and easy to write for my own use. That's also why I saved space by not properly quoting all my variable expansions. ($v instead of "$v")
appears that if you add this to the command line:
-loglevel debug
or
-loglevel verbose
You get more verbose debugging output to the command line.
You can find more debugging info just simply adding the option -loglevel debug, full command will be
ffmpeg -i INPUT OUTPUT -loglevel debug -v verbose
You must declare the reportfile as variable for console.
Problem is all the Dokumentations you can find are not running so ..
I was give 1 day of my live to find the right way ....
Example: for batch/console
cmd.exe /K set FFREPORT=file='C:\ffmpeg\proto\test.log':level=32 && C:\ffmpeg\bin\ffmpeg.exe -loglevel warning -report -i inputfile f outputfile
Exemple Javascript:
var reortlogfile = "cmd.exe /K set FFREPORT=file='C:\ffmpeg\proto\" + filename + ".log':level=32 && C:\ffmpeg\bin\ffmpeg.exe" .......;
You can change the dir and filename how ever you want.
Frank from Berlin
If you just want to know how long it takes for the command to execute, you may consider using the time command. You for example use time ffmpeg -i myvideoofoneminute.aformat out.anotherformat
I execute the following command line
ffmpeg.exe
-i C:\Beema\video-source\DO_U_BEEMA176x144short.avi
-i C:\Beema\video-source\DO_U_BEEMA176x144short.avi
-i C:\Beema\temp\9016730-51056331-stitcheds.avi
-i C:\Beema\video-source\GOTTA_BEEMA176x144short.avi
-y -ac 1 -r 24 -b 25K
C:\Beema\video-out\9a062fb6-d448-48fe-b006-a85d51adf8a1.mpg
The output file in video-out ends up having a single copy of DO_U_BEEMA. I do not understand why ffmpeg is not concatenating.
Any help is dramatically appreciated,
mencoder -oac copy -ovc copy file1 file2 file3 … -o final_movie.mpg
Have you tried with mencoder?
Also are all of the files the same bitrate and dimensions? If not your going to need to make sure all of the video files are identical in these two areas before attempting to combine. It also appears your attempting to combine .avi's with a single .mpg, you'll most likely want to convert the .mpg to a similar format when re-encoding.
Hope this helps.
If it has C:\, it's Windows. use:
copy video1 + video2 + video3
and add more + videoN instances until you get there.
Here is the command that will work for you first cat the files then pipe to ffmpeg
cat C:\Beema\video-source\DO_U_BEEMA176x144short.avi C:\Beema\video-source\DO_U_BEEMA176x144short.avi C:\Beema\temp\9016730-51056331-stitcheds.avi
C:\Beema\video-source\GOTTA_BEEMA176x144short.avi | ffmpeg -f mpeg -i - C:\Beema\video-out\9a062fb6-d448-48fe-b006-a85d51adf8a1.mpg
-i - is important "-" this is the piped input to ffmpeg
Cheers.
I guess ffmpeg cann't do that. It usually takes only one input file. Trying to cat files to input may result in a lump togather, but i guess it won't stitch properly.
Best bet is mencoder or using transcode