I'm trying to batch convert thousands of wav files into 96k m4a files on Mac OS Mojave using ffmpeg in the terminal.
I'm trying to use the following code:
for f in *.wav; do ffmpeg -i "$f" -c:a libfdk_aac -b:a 96k “${f%.wav}.m4a”; done
I'm being given the following error:
Unable to find a suitable output format for '“file.m4a”'
“file.m4a”: Invalid argument
Can anyone help?
Smartquotes are treated as part of the filename.
Use plain quotes instead:
for f in *.wav; do ffmpeg -i "$f" -c:a libfdk_aac -b:a 96k "${f%.wav}.m4a"; done
If you have lots of files to convert, you might want to do that in parallel:
find . -name '*. wav' -type f -print0 | parallel -0 ffmpeg -i {} -c:a libfdk_aac -b:a 96k {.}.m4a
Check this doc for how to work with parallel. If you don't have the tool, install it with brew install parallel.
Scott's answer is perfectly fine too. I like parallel as it also allows me to easily e.g. modify the name of the output file.
Related
Hi I've got a script that i want to scan all sub directories 1/2/3/4/ etc deep but when i've placed an mkv sample file here for example;
/home/storage/movies/folder1/folder2/folder3/sample.mkv
but it doesnt find the .mkv
and it get the error
**/*.mkv: No such file or directory
shopt -s globstar
while true; do
for f in **/*.mkv; do
ffmpeg -i "$f" -c:v libx264 -preset ultrafast -minrate 4.5M -maxrate 4.5M -bufsize 9M -c:a ac3 "${f%mkv}mp4";
rm "$f";
done
sleep 60
done
Can anyone see what is wrong or have any other suggestions
Daniel, it has been 2 months, and I hope you found the solution. If you did not you may try this as quick workaround,
for f in `find . -name *.mkv`; do
You can have a look find's exec option as well
I have a code that using ffmpeg to conver *.avi to *.mp4 on all files in the folder. I want it to run on all folders and sub folders; and to save the result in this subfolder.
I tried already with find but no success
#!/bin/bash
for i in *.avi;
do
ffmpeg -i /location/"$i" -c:v libx264 -preset ultrafast \
-strict -2 -n /location/"$(basename "$i" .avi)".mp4
done
You can use find to find matching files in all sub-directories:
find <top-dir> -iname "*.avi" | while read filename; do ffmpeg -i "$filename" ... "${filename%avi}mp4"; done
Replace ... with your ffmpeg options.
You can also use GNU parallel utility to parallelize processing of found files over multiple CPUs:
find <top-dir> -iname "*.avi" | parallel -i -- ffmpeg -i "{}" ... "{.}.mp4"
I have hundreds of folders containing video, audio, images.. which I need to create video thumbs foreach 10 seconds of video of every video file found (mp4/avi/mov/3gp) and placed in one location /thumbs/.
I have this, which I've been trying to figure out for days.
find . -exec ffmpeg -i {} -vf fps=1/8 {}.png \;
or
find /Users/media/Desktop/videoframes/input/ -regex ".*\.\(mp4\)" -print0 | while read -d $'\0' file; do ffmpeg -i $file -vf fps=1/8 ${file}%d.png done
I know little about the syntax but want to learn more but Im stumped.
Thanks!
I wanted to just comment on an answer to a question very similar to this but I don't have enough rep. I'm looking for a way to change this line of code:
for i in *.mkv; do ffmpeg -i "$i" "${i%.*}.mp4"; done
So that it includes .avi files and so that it can search through nested folders. I want to be able to target /Videos and have the script automatically traverse through the folder tree into /Videos/2016/January, convert all of the video files contained within that folder, then do the same for /Videos/2016/February and so on.
Thanks in advance.
(credit for above line of code goes to LordNeckBeard, from this post.)
Using LordNeckBeard's reference to find, I came up with the following solution:
find ./ -iname '*.avi' -o -iname '*.mkv' -exec bash -c 'ffmpeg -i "{}" -c:v libx265 -preset medium -crf 28 -c:a aac "{}".mp4' \;
Tested and worked exactly how I expected, so it is currently running through the entire library.
If you want to give your converted files a different name to the original, see Parameter Expansion.
If you wish to destructively convert all files, be extremely careful with this command:
find ./ -iname '*.avi' -o -iname '*.mkv' -exec bash -c 'ffmpeg -i "{}" -c:v libx265 -preset medium -crf 28 -c:a aac "{}".mp4 && rm "{}"' \;
NOTE: The command above isn't bulletproof and was removing some files BEFORE the conversion process had finished, meaning I have now lost those files (thank God for backups). I tested with disposable files and have made sure I have a fully functional back up of my data before starting this procedure.
I am trying to convert a directory full of mp3's (with spaces in file names) to m4a.
To convert a single file (this works):
ffmpeg -i Traffic.mp3 -c:a libfaac -vn Traffic.m4a
The command that is failing (on OS X Mavericks):
find . -name \*.mp3 -print0 | xargs -0 ffmpeg -i {} -c:a libfaac -vn {}.m4a
find . -name '*.mp3' -type f -exec bash -c 'ffmpeg -i "$0" -c:a libfaac -vn "${0%.mp3}.m4a"' {} \;
Why do you use xargs? find -exec is enough:
find . -name \*.mp3 -exec ffmpeg -i {} -c:a libfaac -vn {}.m4a \;
The problem is that xargs is more similar to find -exec … + than find -exec … \;. It launches preferably just one instance of the command, replacing a single {} by sequence of space separated items read from input (more or less). If you want xargs to behave like find -exec … \;, you need to specify -I{} (xargs -0 -I{} ffmpeg …).
This converts Traffic.mp3 to Traffic.mp3.m4a. If you want to save the conversion result to Traffic.m4a, you can
rename the files after the conversion (not a very clean solution),
execute shell in the -exec action and remove the .mp3 before appending .m4a or
use xargs after sedding the .mp3 extension away from find result.
I vote for the last option as it executes less processes (and shell is quite a big one, though ffmpeg would be difinitely so large that the difference in performance is negligible).
find . -name \*.mp3 | sed 's/\.mp3$//' | xargs -I{} ffmpeg -i {}.mp3 -c:a libfaac -vn {}.m4a