Linux shell script

I'm planning to convert a couple of video files my father has recored from *.TS to *.mkv. Since he has given me about 100 files I'd like to use a simple shell script. Basically I'd like to loop through the files, convert each file and remove the corresponding *.TS file. However, some files cannot be easily converted and I need to convert them to *.mp4 first, and then to *.mkv. Which is why I don't want to delete the files where the convert process didn't work. Therfore, I can't use a simple for , do && . I somehow need to check command1's return value. Is there a simple solution for this problem?

You probably going have to be more specific on the conditions for file conversion, but here a is a script that I used (convert mkv 10bit to mkv 8bit) that might be useful to start:

#!/bin/bash
find $1 -iname '*.mkv' | while read f ; do
	if ffprobe "$f" 2>&1 | grep "High 10"; then
        echo "CONVERTING: $f"
        x264 --preset veryfast --tune animation --crf 16 -o  "${f%*.mkv}"-8bit.mkv "$f"
        mkvmerge -o "${f%*.mkv} [8bit].mkv" -D "$f" "${f%*.mkv}"-8bit.mkv
	rm "${f%*.mkv}-8bit.mkv"
		
		if [ -f "${f%*.mkv} [8bit].mkv" ]; then
			rm "$f"
		fi
    fi
done

I use the find command to scan sub folders and give me the full path, the ${f%*.mkv} part gives filename without the extension and I know the output file will be the filename with the suffix ' [8bit].mkv' so I verify if exists and if it does, it deletes the original.

2 Likes

thanks, I'll try something similar :slight_smile:

You can use the variable $? to check return value of the previous command.

Between that and @nakamura's post, you should be able to put something together.

It's important to note that MKV is a container. Don't confuse it with a format. You could have a .mkv file that contains TS streams in it. Based on what you're asking for, it sounds like you want an H.264 or H.265 stream inside the mkv container.

You absolutely can.

# this will have the entire script stop on failure, 
# so there is no reason for you to do any checks.
set -e

find $1 -iname '*.ts' | while read f ; do

    avconv -i $f -c:a copy -c:v copy ${f%*.ts}.mp4
    avconv -i ${f%*.ts}.mp4 -c:a copy -c:v copy ${f%*.ts}.mkv

done

EDIT: This isn't tested, but it's non-destructive, so I would use a test file and test directory before you run this against all your files. Just to be sure.

2 Likes

Thanks again. Yeah, I know that MKV is a container, I was a bit sloppy though^^
The actual video format remains the same.

Concerning your script: To delete the the files I'd have to do the following:

# this will have the entire script stop on failure, 
# so there is no reason for you to do any checks.
set -e

find $1 -iname '*.ts' | while read f ; do

    avconv -i $f -c:a copy -c:v copy ${f%*.ts}.mp4
    rm -f $f
    avconv -i ${f%*.ts}.mp4 -c:a copy -c:v copy ${f%*.ts}.mkv
    rm -f ${f%*.ts}.mp4

done
1 Like

That should work.

Glad to help!

1 Like

Just in case someone else is interested, I went with the following script:

#! /bin/bash

for f in *.*; do
        if [ ${f: -4} == ".TS4" ] || [ ${f: -3} == ".TS" ]
        then
                ffmpeg -i "$f" -sn -codec copy "${f%.*}.mkv"
                # check if conversion was successful
                rc=$?
                if [ $rc == 0  ]
                then
                        rm -f "$f"
                else     
                        ffmpeg -i "$f" -sn -codec copy "${f%.*}.mp4"
                        rm -f "$f"
                        ffmpeg -i "${f%.*}.mp4" -sn -codec copy "${f%.*.mkv}"
                        rm -f "${f%.*}.mp4"
                fi
        fi
done
1 Like