LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Making a batch shell script to convert, merge and append (join) movie's to mkv (https://www.linuxquestions.org/questions/programming-9/making-a-batch-shell-script-to-convert-merge-and-append-join-movies-to-mkv-773699/)

mnt_schred 12-05-2009 02:56 PM

Making a batch shell script to convert, merge and append (join) movie's to mkv
 
My movie collection (1800+) titles is on a linux server, consiting of four types of files:
  • .mkv (matroska)
  • .avi
  • .srt
  • .sub
Some of theme are unique, bot a lot are split into two, three or even four files (due to the fact a lot of people still split movies into 700 Mb for CD's). What I want to achieve is the following:

A Shell script (bash) which does the following:
  1. Take all the avi files with an subtitle file (.sub or .srt) and merge them (mkvmerge -o file.mkv file.avi file.srt OR file.sub
  2. Take all the mkv's with the format 'file.cdX.mkv' (X beïng 1,2,3,4) and append them with mkvmerge -0 file.mkv file.cd1.mkv +file.cd2.mkv ... (notice the + sign)

Afterwards, the remaining .avi files I want to merge with the command 'avimerge' to single .avi's.

The goal is to clean the collection to unique .avi files (without subtitle) and unique .mkv files (with subs) with one file per movie.

I've tested mkvmerge with two mkv's with embedded subtitles, and this is handled correctly :)

The advice I'm seeking:

What's the best approach? Making scripts to sort the files first?
Or make a big script to do it all? Some pointers?

I think the first step is to move all .avi's which have an .srt file to a subdirectory. Then I can do mkvmerge -o file.mkv file.avi file.srt for all file.avi.

tuxdev 12-05-2009 05:52 PM

Code:

#!/bin/bash
AVI_DIR="avi"
SUB_DIR="sub"
SRT_DIR="srt"
MKV_DIR="mkv"
for AVI in "$AVI_DIR"/*.avi ; do
  NAME=$(basename "$AVI" .avi)
  if [[ -r "$SUB_DIR/$NAME.sub" ]] ; then
      echo "Subbing $NAME (SUB)"
      mkvmerge -o "$MKV_DIR/$NAME.mkv" "$AVI" "$SUB_DIR/$NAME.sub"
  elif [[ -r "$SRT_DIR/$NAME.srt" ]] ; then
      echo "Subbing $NAME (SRT)"
      mkvmerge -o "$MKV_DIR/$NAME.mkv" "$AVI" "$SRT_DIR/$NAME.srt"
  else
      echo "No subtitles found for $NAME"
  fi
done

Code:

#!/bin/bash
for FIRST in ./*.cd1.mkv ; do
  NAME=$(basename "$FIRST" .cd1.mkv)
  REST=("./$NAME".cd[^1].mkv)
  mkvmerge -o "$NAME.mkv" "$FIRST" "${REST[@]/#/+}"
done


mnt_schred 12-05-2009 06:57 PM

Wow, that's a fast reply, thanks!

I've tried it with a few samples, and the srt's worked, the sub's didn't.
But, it turned out that mkvmerge doesn't support .sub's yet.
So, I have to find a way to convert the sub's into .srt's first, but I'll look into that seperately. (I think that won't be much of a problem though: http://www.robelix.com/sub2srt/)

A problem is that because the original files are not deleted, it's difficult to see which files can be deleted afterwards. Maybe it's possible to build in a feature that the merged .srt's and .avi's are moved into a 'done' folder?

It's also possible to delete them after processing off course. But that's more dangerous...

This is the script in it's current form:

Code:


#!/bin/bash
AVI_DIR="avi"
SUB_DIR="sub"
SRT_DIR="srt"
MKV_DIR="mkv"
for AVI in "$AVI_DIR"/*.avi ; do
  NAME=$(basename "$AVI" .avi)
  if [[ -r "$SRT_DIR/$NAME.srt" ]] ; then
      echo "Subbing $NAME (SRT)"
      mkvmerge -o "$MKV_DIR/$NAME.mkv" "$AVI" "$SRT_DIR/$NAME.srt"
      rm "$AVI"
      rm "$SRT_DIR/$NAME.srt"
  else
      echo "No subtitles found for $NAME"
  fi
done


The seccond script doesn't work:

beryllium:/fun/UITZOEKEN/test2/mkv # ll
total 1428404
-rw-r--r-- 1 root root 729654273 2009-12-06 01:54 Der Untergang (2004).cd1.mkv
-rw-r--r-- 1 root root 731584186 2009-12-06 01:54 Der Untergang (2004).cd2.mkv
-rwxr-xr-x 1 root root 161 2009-12-06 01:55 merge_films.sh
beryllium:/fun/UITZOEKEN/test2/mkv # ./merge_films.sh
mkvmerge v2.9.8 ('C'est le bon') built on Aug 13 2009 19:49:27
Error: no output file name was given.

edit: changed -0 into -o, that works now. However, now because of the spaces something goes awry:

beryllium:/mnt/raid/5primary/fun/UITZOEKEN/test2/mkv # ./merge_films.sh
mkvmerge v2.9.8 ('C'est le bon') built on Aug 13 2009 19:49:27
Error: The source file './Der' could not be opened successfully, or retrieving its size by seeking to the end did not work.

tuxdev 12-05-2009 07:44 PM

It's word splitting.. quoting the last arg should fix it

mnt_schred 12-06-2009 06:43 AM

I thought is was something like that, but isn't the argument already in "?
Code:

mkvmerge -0 "$NAME.mkv" "$FIRST" "${REST[@]/#/+}"
And, I'd like to enter an delete option as well for the original files; would

Code:

rm $FIRST
rm ${REST[@]/#}

do?

Thanks so far, already 210 files have been transformed into mkv :)

tuxdev 12-06-2009 10:08 AM

Quote:

I thought is was something like that, but isn't the argument already in "?
It is when I edit it..

Actually, I suggest you print out all the old files that have been processed - if there's some error and one of the mkv's weren't properly generated, you don't want to lose those old files. Once you've verified them all, you can run
Code:

while read FILE ; do
rm "$FILE"
done < processed-files


mnt_schred 12-07-2009 06:40 AM

That's a good idea, but I've tested the mkvmerge extensively which works very good (and only will execute after numerous checks) so I'll still delete them (plus it would require extreme disk space, almost 1/2 TB.).

But I'm afraid I still don't get what's wrong with
Code:

mkvmerge -0 "$NAME.mkv" "$FIRST" "${REST[@]/#/+}"
Should 'REST[@]' be encapsulated in "'s as well?

edit: no... apparently.

tuxdev 12-07-2009 09:32 AM

ah, I made REST *all* of the non-first discs, not just the one for "$NAME".. oops

mnt_schred 12-07-2009 11:51 AM

So it should be:

Code:

#!/bin/bash
for FIRST in ./*.cd1.mkv ; do
  NAME=$(basename "$FIRST" .cd1.mkv)
  REST=("./$NAME".cd[^1].mkv)
  mkvmerge -o "$NAME.mkv" "$FIRST" "${REST[@]/#/+}"
done

which works :) Great!
If it works with a few tests I'll use it in the form

Code:

#!/bin/bash
for FIRST in ./*.cd1.mkv ; do
  NAME=$(basename "$FIRST" .cd1.mkv)
  REST=("./$NAME".cd[^1].mkv)
  mkvmerge -o "$NAME.mkv" "$FIRST" "${REST[@]/#/+}"
  rm "$FIRST"
  rm "${REST[@]/#}"
done


I also made an version for avimerge (my movies without subs are usualy avi's):

Code:

#!/bin/bash
for FIRST in ./*.cd1.avi; do
  NAME=$(basename "$FIRST" .cd1.avi)
  REST=("./$NAME".cd[^1].avi)
  avimerge -o "$NAME.avi" -i "$FIRST" "${REST[@]/#}"
  rm "$FIRST"
  rm "${REST[@]/#}"
done

(notice that avimerge doesn't need a + sign before the inputfiles, because avimerge can only append, while mkvmerge can also join.)


All times are GMT -5. The time now is 01:14 PM.