I use a batch file below to concatenate video files using avidemux's cli executable. The reason why I pipe most of avidemux's output into 00_log.log is that its output is highly verbose and shoveling this to a text file appears to leave behind more helpful status or critical error messages displayed on the console. However, I'd like to see what file avidemux is working on at the time any error message pops up. Below, everything following ECHO is not displayed in the console.
Commenting or removing #echo off simply relays the ECHO lines below at the beginning of the batch job rather than alongside avidemux's console output, thus limiting its use.
#echo off
>00_log.log (
ECHO Joining foo.mp4
"C:\Program Files\Avidemux\avidemux_cli.exe" --load 1.mp4 --append 2.mp4 --output-format MP4v2 --save D:\foo.mp4
ECHO Joining foo2.mp4
"C:\Program Files\Avidemux\avidemux_cli.exe" --load 3.mp4 --append 4.mp4 --output-format MP4v2 --save D:\foo2.mp4
)
ECHO Job Done
#Pause
Simply redirect the avidemux_cli output to the log file, but not the rest.
So, use something like:
#echo off
ECHO Joining foo.mp4
"C:\Program Files\Avidemux\avidemux_cli.exe" --load 1.mp4 --append 2.mp4 --output-format MP4v2 --save D:\foo.mp4 >> 00_log.log
ECHO Joining foo2.mp4
"C:\Program Files\Avidemux\avidemux_cli.exe" --load 3.mp4 --append 4.mp4 --output-format MP4v2 --save D:\foo2.mp4 >> 00_log.log
ECHO Job Done
#Pause
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 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.
I have a script for playing movies through mplayer, for which I am attempting to include automatic conversion of 3D to 2D. Here is the relevant cmd line as it appears in the script
mplayer -fs "${g[$i]}" -ss $f "${d%.*}".* -hardframedrop -nocorrect-pts -identify &>> log.txt
This does not render to 2D even though "${g[$i]}" has the needed option
echo "${g[$i]}"
-vo gl:stereo=3
But if I modify the cmd line to show the option directly, the movie is shown in 2D
mplayer -fs -vo gl:stereo=3 -ss $f "${d%.*}".* -hardframedrop -nocorrect-pts -identify &>> log.txt
The problem seems to be that mplayer interprets the option as a filename when delivered via ${g[$i]}, thus from log.txt
Playing -vo gl:stereo=3 .
File not found: ' -vo gl:stereo=3 '
Failed to open -vo gl:stereo=3 .
How can I prevent this?
You are passing " -vo gl:stereo=3 " which is indeed invalid. You should be passing "-vo" followed by "gl:stereo=3". In other words, it should be passed as two separate arguments without the leading and trailing spaces.
The easiest workaround to make this happen is to skip the quotes around ${g[$i]}:
mplayer -fs ${g[$i]} -ss $f "${d%.*}".* -hardframedrop -nocorrect-pts -identify &>> log.txt
The more robust workaround would be to store the arguments separately in an array, e.g. opts=("-vo" "gl:stereo=3") and using "${opt[#]}", but Bash does not support multidimensional arrays so this may require some deeper changes to your script.
I have stuttering, seeking, and general playback issues when playing large mkv files through my Plex Media Server setup. I have been looking around for a way to automate scheduled tasks to move everything to mp4. The objective is:
Copy mkv files into mp4 preserving subtitles of every kind. Put the new file in the same subdir, and delete previous mkv version if conversion went successful.
When I tried to run ffmpeg on a loop, I run into the problem described here:
https://unix.stackexchange.com/questions/36310/strange-errors-when-using-ffmpeg-in-a-loop
This is my first adventure on shell scripting and I am pretty much stumbling around and trying to understand the syntax and philosophy of it. What I understand is that they use a file descriptor to redirect ffmpeg output to /dev/null.
The problem with that solution is that I would need to check ffmpeg output for errors to decide whether to delete the previous file or not. Furthermore, there is a common error when converting from picture based subtitles streams, which I circumvent by using a script I found (http://www.computernerdfromhell.com/blog/automatically-extract-subtitles-from-mkv/) to work after some modifications to my needs.
After much frustration I ended modifying the script so much that it does not serve to its purpose. It does not check for errors. Anyways, I will post it here. Mind you that this is my first shell script ever, and almost everything is confusing about it. The problem with this, is that I had to ditch my error checking and I am eliminating files that errored when converting. Losing the original without a valid copy.
#!/bin/bash
FOLDERS=( "/mnt/stg4usb/media0/test/matroska1" "/mnt/stg4usb/media0/test/season1" "/mnt/stg4usb/media0/test/secondtest")
FLAGS="-y -metadata title="" -c:v copy -map 0 -c:a libfdk_aac -ac 2 -movflags +faststart"
COUNTER=0
LOGFILE=batch-$(date +"%Y%m%d-%H%M%S").log
for FOLDER in "${FOLDERS[#]}"
do
echo "---===> STARTING folder: '$FOLDER'"
find $FOLDER -name "*.mkv" | while read line; do
OUTPUT=""
DATE=$(date +"%Y-%m-%d")
TIME=$(date +"%H:%M:%S")
COUNTER=$((COUNTER+1))
FILE=$(basename "$line")
DIR=$(dirname "${line}")
echo $'\n'$'\n'"[$COUNTER][$DATE][$TIME][FILE:'${line%.mkv}.mp4']"$'\n'
echo "#### Transcoding ####"'\n'
ffmpeg -i $line $FLAGS -sn "${line%.mkv}.mp4" < /dev/null
echo "#### Extracting subtitles ###"'\n''\n'
mkvmerge -i "$line" | grep 'subtitles' | while read subline
do
# Grep the number of the subtitle track
tracknumber=`echo $subline | egrep -o "[0-9]{1,2}" | head -1`
# Get base name for subtitle
subtitlename=${line%.*}
# Extract the track to a .tmp file
mkvextract tracks "$line" $tracknumber:"$subtitlename.$tracknumber.srt" < /dev/null
chmod g+rw "$subtitlename.$tracknumber"* < /dev/null
done
rm -frv "$line" < /dev/null
echo "Finished: $(date +"%Y%m%d-%H%M%S")"
done
echo '\n'"<===--- DONE with folder: '$FOLDER'"$'\n'$'\n' >> $LOGFILE
done
exit 0
So, basically, the idea is: run ffmpeg on a loop for all mkv under a directory and subdirectories (I was using find). Check it for all possible errors. If errors, try again without subtitles and extract the subtitles using mkvextract, else everything went ok, and delete the previous file.
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