I am concatenating a bunch of files on a windows 10 box into a single file using "ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4". This works fine when I generate list.txt in the required format.
What I am wanting is to not have to generate the file first and instead pipe the filenames in as the examples here show for *nix.
I have tried as follows "ffmpeg -f concat safe 0 -i <(for %i in (*.ts) do #echo file '%i') -c copy output.mp4" but I get "The system cannot find the file specified.".
Any idea's how to make this work?
Command substitution on Unix...
ffmpeg -i $(some-command-that-generates-an-url/path) [...]
...is possible on Windows through a for-loop:
FOR /F "delims=" %A IN ('some-command-that-generates-an-url/path') DO ffmpeg -i %A
Process substitution on the other hand, as you describe, isn't possible on Windows. Temporary files are inevitable.
Related
I have 2 preset .json files(from the GUI version on windows) to convert mkv to mp4.
converts to h264 and adds subtitle 1
converts to h264
I'm only trying to get no.2 to work at this stage.
for i in `*.mkv`; do HandBrakeCLI --preset-import-file HPRESET.json -Z "MYPRESET" --output *.mp4; done
no output name
HandBrakeCLI -i $1 --preset-import-gui HPRESET.json -Z "MYPRESET" --output $1.mp4
errors on output name
for i in `*.mkv`; do HandBrakeCLI --title $i --preset "Very Fast 1080p30" --output *.mp4; done
errors on output name AND not valid preset.
$ for i in `seq 4`; do HandBrakeCLI --input /dev/dvd --title $i --preset Normal --output NameOfDisc_Title$i.mp4; done
copied this from another stackoverflow question, but outputs as 1.mp4 and then 2.mp4 etc.
You can extract the filename without extension with something like that:
noext=${i%.*}
Example:
╰─$ for i in *.mkv; do echo "$i"; noext=${i%.*}; echo "$noext"; done
asdf.mkv
asdf
test.mkv
test
Same loop, different notation:
for i in *.mkv
do
#put the commands you want to run after "do" and before "done"
echo "$i"
noext=${i%.*}
echo "$noext"
done
Note that the for command will search any file in the current directory ending with .mkv. For each file it has found, it will save the files name into the variable $i, then execute the commands after do, then save the next files name into the variable $i and execute the commands between do and done. It will repeat that cycle until every file which has been found is processed.
As I have no experience with handbrake presets, here a solution with ffmpeg:
for i in *.mkv
do
#put the commands you want to run after "do" and before "done"
noext=${i%.*}
ffmpeg -i "$i" -c:v libx264 -c:a copy -c:s copy "$noext.mp4"
done
I have two folders "Left channel" and "Right channel". Each folder contains mono files with same names. Example: "Left channel" contains "A.wav", "B.wav", "C.wav" and "Right channel" contains "A.wav", "B.wav", "C.wav". I need to make stereo files for each mono files.
So I have to combine
ffmpeg -i left.mp3 -i right.mp3 -filter_complex "[0:a][1:a]join=inputs=2:channel_layout=stereo[a]" -map "[a]" output.mp3
and
for file in /dir/* do ffmpeg -i ...; done
How can I go through all mono files and make bunch of stereo files from these mono files with ffmpeg in bash?
Would you please try the following:
#!/bin/bash
lch="Left channel"; rch="Right channel" # directory names of wav files
for f in "dir/$lch/"*.wav; do
fname=${f##*/} # filename such as "A.wav"
outfile="output_${fname%.*}.mp3" # output filename such as "output_A.mp3"
if [[ -f dir/$lch/$fname && dir/$rch/$fname ]]; then
echo ffmpeg -i "dir/$lch/$fname" -i "dir/$rch/$fname" -filter_complex "[0:a][1:a]join=inputs=2:channel_layout=stereo[a]" -map "[a]" "$outfile"
fi
done
It just outputs the command line as a dry run. If the output looks good, drop echo and run again.
Please note the output of echo removes the double quotes around the filenames. If you copy the output of echo and execute it on the command line, it will not work well.
I'm trying to use ffmpeg to convert some .m4a audio files to .mp3, and have come across something that has me stumped. I'd like to create the .mp3 in the same location and with the same filename as the .m4a, and so I'm using a combination of find/exec and a bash script to do this, as follows:
find /Volumes/Untitled/ -name '[!.]*' -name '*.m4a' -exec ./m4atomp3.sh {} \;
where m4atomp3.sh looks like:
#!/usr/bin/env bash
[[ -f "$1" ]] || { echo "$1 not found" ; exit 1 ; }
P="$1"
echo "$P is the full filename"
filename=${P%.*}
echo "$filename is the stripped filename"
m4afilename=\"$filename.m4a\"
echo "$m4afilename is the input filename"
mp3filename=\"$filename.mp3\"
echo "$mp3filename is the output filename"
mycmd="/Users/nickstyles/Downloads/ffmpeg -i "$m4afilename" -codec:a libmp3lame -qscale:a 2 -nostdin "$mp3filename
echo $mycmd
$mycmd
Whenever I try this, it fails because ffmpeg doesn't find the file, seemingly because of the whitespace in the filename, e.g if the file was called /Volumes/Untitled/My M4As/My M4A.m4a I would see:
ffmpeg version N-99346-g003b5c800f-tessus https://evermeet.cx/ffmpeg/ Copyright (c) 2000-2020 the FFmpeg developers
built with Apple clang version 11.0.0 (clang-1100.0.33.17)
[configuration details]
"/Volumes/Untitled/My: No such file or directory
However, if I just paste what is returned by echo $mycmd into the command line, e.g:
/Users/nickstyles/Downloads/ffmpeg -i "/Volumes/Untitled/My M4As/My M4A.m4a" -codec:a libmp3lame -qscale:a 2 -nostdin "/Volumes/Untitled/My M4As/My M4A.mp3"
then it works absolutely fine. I'm sure I'm missing something very obvious, which hopefully someone can spot!
As Benjamin W. pointed out the problem was that the variable was still getting split by bash, due to WordSplitting, and the quotes I was adding to the content of the variable were not helping against this. The key was to ensure that the quotes were placed around the variable itself like:
m4afilename=$filename.m4a
echo "$m4afilename is the input filename"
mp3filename=$filename.mp3
echo "$mp3filename is the output filename"
/Users/nickstyles/Downloads/ffmpeg -i "$m4afilename" -codec:a libmp3lame -qscale:a 2 -nostdin "$mp3filename"
and now this works!
Try this : mycmd="/Users/nickstyles/Downloads/ffmpeg -i $m4afilename -codec:a libmp3lame -qscale:a 2 -nostdin $mp3filename"
In bash, you can put variable straight into double quotes.
I recently discovered youtube-dl and I wanted to make a batch file within the folder of the youtube-dl executable that asks for a url and uses that url in the
youtube-dl --extract-audio --audio-format mp3 -i -o songs\%(title)s.%(ext)s <video URL>
command, which saves the video as an mp3 file in the \songs\ folder in the same filepath as the executable. The command works fine if I copy-paste it into a command prompt and replace <video url> with the actual url, but when I try to put this in a batch file (e.g. with set var1="") it uses the variable's name in the command (youtube-dl --extract-audio --audio-format mp3 -i -o songs\%(title)s.%(ext)s var1).
I've found this, and it seems to be what I'm looking for, but it didn't make any sense.
When copying the command into a batch file, you'll need to replace % with %%, so that the output template parameter to the -o option will be interpreted correctly (i.e. as the string %(title)s.%(ext)s).
If you prefer to be prompted to enter the link, batch file may look like this:
set /p var1= "Enter youtube link: "
youtube-dl --extract-audio --audio-format mp3 -i -o songs\%%(title)s.%%(ext)s %var1%
Or, just set var1 before calling the script (set var1=youtube-link), or in the script itself.
Situation:
AVI files sometimes come in two files filename-cd1.avi and filename-cd2.avi.
I use the following line in a bash script on my iMac to copy the two cd files into a single AVI file:
MENCODER -ovc copy -oac copy *CD1.avi *CD2.avi -o "Joined Movie.avi" > /dev/null 2>&1
What I'd like to do is retain the base file name. So:
of file name with '-cd2' is found, like say: OldMovie-cd2.avi
What I'm wanting to do is store "OldMovie" as a variable so that I can tell mencoder to perform the copy on the two files and… Here's the kicker - I'd LOVE to have resulting file be "OldMovie.avi" which is the base name of the two cd sub files.
Make sense? Geez I hope so.
Appreciate the help, I've googled for hours without a solution.
Randy
for avi in *-cd2.avi; do
base=`echo $avi | sed 's+-cd2\.avi+$\.avi+g'`
echo base is $base
echo looking for ${base}-cd1.avi
if [ -f "${base}-cd1.avi" ]; then
echo Found ${base}-cd1.avi
MENCODER -ovc copy -oac copy ${base}-cd1.avi ${base}-cd2.avi -o "${base}.avi" > /dev/null 2>&1
else
echo Did not find ${base}-cd1.avi
fi
done