I'm trying to derive the numeric representation of a sound file's phase.
FFMPEG's aphasemeter filter seems to fit the bill for computing this number; the docs explicitly say:
The filter also exports the frame metadata lavfi.aphasemeter.phase which represents mean phase of current audio frame. Value is in range [-1, 1]. The -1 means left and right channels are completely out of phase and 1 means channels are in phase.
https://ffmpeg.org/ffmpeg-filters.html#aphasemeter
However, I can't seem to figure out how to use this filter to get that numeric value. When I experiment with various commands, I get various error messages. For example, ffmpeg -i input_file.wav -f aphasemeter.phase says I need an output, but ffmpeg -i input_file.wav -f aphasemeter.phase output_file.txt produces is not a suitable output format \ output_file.txt: Invalid argument
I'm looking for that -1 through 1 value; a graphical representation of that--though seemingly the main point of that filter--is not what I'm looking for.
Any ideas?
In case it matters, I'm using the WSL, having installed ffmpeg by apt-get.
Logged metadata values can be accessed and exported using the (a)metadata filter.
ffmpeg -i in.wav -af aphasemeter=video=0,ametadata=print:file=inwav-phase.txt -f null -
The text file will have the data in the format,
...
frame:105 pts:107512 pts_time:2.23983
lavfi.aphasemeter.phase=0.600750
frame:106 pts:108536 pts_time:2.26117
lavfi.aphasemeter.phase=0.554201
...
Related
I would be so glad to have some help with this.
I have video rushes in this form : black > sequence > black > sequence...
I need the start/end timecodes of each sequences (no black) to create segments on another software so I wondering if it's possible with the blackdetect filter of FFmpeg to output only the sequences data in a csv file. No problem with the simple command line to have the blacks but I'm still at this point with unsuccess others test.
The goal is automate this for multiple files by import the csv in a RPA.
Thank you very much.
You cannot do that with ffmpeg by itself, but with a bit of help from a script (i.e., Python) you can decode the frame metadata. The following filtergraph outputs the black detect output to stdout:
ffmpeg -i input -vf blackdetect,metadata=print:file=- -f null dev/null`
Your script shall capture the pipe output, and parse the output to retrieve the pts and detect either black_start and black_end and reformat and output to a csv file.
If your other program is flexible, you can alternately specify output file name file=xxx and do the parsing there.
I have This Parisienne-type Font file and I want to write on a gif using that font but the output font is never Parisienne, it always comes out as normal Arial
the command
ffmpeg -i C:\Users\1997\www\post2\css\back2.gif -vf "drawtext=fontfile='C\:\\Windows\\Fonts\\2.ttf':text='Darbuka 70':fontcolor=#5c391685:fontsize=160::x=(w-text_w)/2:y=20" C:\Users\1997\www\post2\css\output.mp4
This is how the font file looks:
the output:
It's likely due to not having enough escape characters (\). You need one for FFmpeg and double them for shell. So, try
fontfile='C\\\\:/Windows/Fonts/2.ttf'
Four \'s worked when I tested in Python, but if it doesn't add/subtract a pair at a time to see which works for you.
Last, if you want to see if fontfile option is set properly or not, add -loglevel debug option and look in the log for a line like:
[Parsed_drawtext_2 # 0000015e54962a80] Setting 'fontfile' to value 'C:/Windows/Fonts/2.ttf'
If it's not properly escaped, you'd see a log like:
[Parsed_drawtext_2 # 000001c010782440] Setting 'fontfile' to value 'C'
[Parsed_drawtext_2 # 000001c010782440] Setting 'text' to value '/Windows/Fonts/2.ttf'
P.S., I cheated and used / for directory separator. If you want to use \, the same rule applies. You need a several \'s for each \. See documentation
So when specifying a video-filter to display current video-time in 'hms' layout, the filter appends a millisecond value after the seconds-field.
I want to eliminate the milliseconds portion.
So far, my invoked cmd looks like:
ffplay myfile.mp4 -vf "drawtext=text='%{pts \: hms}':fontsize=20:fontcolor=white: box=1: boxcolor=black"
i.e. instead of: 00:00:01.001 I want just 00:00:01 to display.
[One might have thought that there would exist an 'hmsm' for the former,
and that 'hms' would be the latter, but it just doesn't work that way.] (sigh)
According to the documentation:
hms stands for a formatted [-]HH:MM:SS.mmm timestamp with millisecond accuracy.
And there's no way to customize this timestamp format. At least not for the hms format.
The same documentation:
If the format is set to localtime or gmtime, a third argument may be supplied: a strftime() format string. By default, YYYY-MM-DD HH:MM:SS format will be used.
So text='%{pts\:gmtime}' without any additional arguments puts out 1970-01-01 00:00:00 (Unix epoch).
To have it put out 00:00:00 set the 2nd argument to 0 and the 3rd to %H:%M:%S.
As the pts function can take up to 3 arguments, make sure you escape the colons twice on Windows and three times on Unix to prevent %M and %S from being interpreted as a possible 4th or 5th argument.
Windows:
ffplay -vf "drawtext=text='%{pts\:gmtime\:0\:%H\\\:%M\\\:%S}':x=1:y=1:fontsize=20:fontcolor=white:box=1:boxcolor=black:boxborderw=2" myfile.mp4
Unix:
ffplay -vf "drawtext=text='%{pts\:gmtime\:0\:%H\\\\\:%M\\\\\:%S}':x=1:y=1:fontsize=20:fontcolor=white:box=1:boxcolor=black:boxborderw=2" myfile.mp4
Compared to your initial command I've also added :x=1:y=1 and :boxborderw=2. It adds a small border around the text and positions the text nicely centered.
It's a matter of taste of course. You can remove it if you don't like it.
I'm attempting to scale image(s) that have any given name. I've found my script is failing on files that have numbers in the name. "0% financing", "24 Hour", etc. The other files are working fine, so it's not the script itself. I get:
[image2 # 0x7fbce2008000] Could find no file with path '/path/to/0% image.jpeg' and index in the range 0-4
How can I tell ffmpeg that this isn't a search pattern, or sequential numbered files ? There's only 1 jpeg in each location, and I do not have control of the file names to change them.
-update-
I've figured out the command
ffmpeg -pattern_type none -i /path/to/0%\ image/0%\ image.jpeg -vf scale=320:-1 /path/to/0%\ image/0%\ image.out.jpeg
gets me past the initial problem, but the output won't work because I can't get it now to escape the final argument. If I am in the directory (so no path) and change the output to just out.jpeg it will work, so I'm confident the first error is corrected.
Now I need to figure out how to use spaces in the path in the output argument? I've tried surrounding it in quotes:
"0% image.out.jpeg"
regular escapes:
0%\ image.out.jpeg
and surrounding it in quotes and using escapes at the same time:
"0%\ image.out.jpeg"
I'd like to be able to add/edit video metadata titles to multiple files at once or with a single command, but I don't know how to tell ffmpeg to do this.
I read a similar post on the Ubuntu Forums, but I have never used string manipulation in Linux before, so the commands I'm seeing in the post are way out of my comprehension at the moment, and much of the discussion goes over my head.
I've got all of my video files in a filename format that includes the show name, the episode number, and episode title. For example:
show_name - episode_number - episode_title.extension
Bleach - 001 - A Shinigami Is Born!.avi
Is there a simple way to read the title and episode number from the filename and put it into a metadata tag without having to go through each and every file manually?
EDIT 1: So I found out that I can iterate through files in a directory, and echo the filename, and I was told by a friend to try bash to parse the strings and return values from that to use in the ffmpeg command line. The problem is, I have absolutely no idea how to do this. The string manipulation in bash is very confusing on first look, and I can't seem to get it to output what I want into my variables. My test bash:
for file in "Bleach - 206 - The Past Chapter Begins! The Truth from 110 Years Ago.mkv"; do extension=${file##*.} showName=${file%% *} episode=${file:9:3}; echo Extension: $extension Show: $showName Episode: $episode; done
That outputs
Extension: mkv Show: Bleach Episode: 206
Which are all the variables I'm going to need, I just don't know how to move those to be run in ffmpeg now.
EDIT 2: I believe I was able, through much trial and error, to find a bash command that would do exactly what I wanted.
for file in *; do newname=${file:0:-4}_2 ext=${file##*.} filename=${file} showname=${file%% *} episode=${file:9:3} nameext=${file##*- } title=${nameext%.*}; ffmpeg -i "$filename" -metadata title="$title" -metadata track=$episode -metadata album=$showname -c copy "$newname.$ext"; mv -f "$newname.$ext" "$filename"; done
This lets me parse the information from the filename, copy it to some variables, and then run ffmpeg using those variables. It outputs to a second file, then moves that file to the original location, overwriting the original. One could remove that section out if you're not sure about how it's going to parse your files, but I'm glad I was able to get a solution that works for me.