0

i have created this shell script to encode videos using ffmpeg. i need to maintain the folder structure of input and output folder automatically when i run this script.

Problem : As of now, it moves all videos to root of destination directory. it need to create subfolder and output file should save in it.

Input folder:

Folder1
--sub_folder
---video1.mkv
---video2.ts
---video3.mp4
Folder2
---cat.mkv
---mouse.ts
---train.mp4

Expected Output folder:

Folder1
--sub_folder
---video1.mp4
---video2.mp4
---video3.mp4
Folder2
---cat.mp4
---mouse.mp4
---train.mp4

Code :

srcDir=$1
destDir=$2

for filename in $(find "$srcDir" -type f); do

        basePath=${filename%.*}
        baseName=${basePath##*/}

        audioformat=$(ffprobe -loglevel error -select_streams a:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$filename")
        videoformat=$(ffprobe -loglevel error -select_streams v:0 -show_entries stream=codec_name -of default=nw=1:nk=1 "$filename")

        if [ "$audioformat" == "aac" ] &&  [ "$videoformat" == "h264" ] ; then
                echo $filename
                echo $audioformat + $videoformat
                ffmpeg -i "$filename" -y -c:v copy -c:a copy "$destDir"/"$baseName.mp4" -hide_banner -loglevel warning 
        elif [ "$audioformat" == "aac" ] &&  [ "$videoformat" != "h264" ] ; then
                echo $filename
                echo $audioformat + $videoformat
                ffmpeg -i "$filename" -y -c:v libx264 -c:a copy "$destDir"/"$baseName.mp4" -hide_banner -loglevel warning 
        elif [ "$audioformat" != "aac" ] &&  [ "$videoformat" == "h264" ] ; then
                echo $filename
                echo $audioformat + $videoformat
                ffmpeg -i "$filename" -y -c:v copy -c:a aac "$destDir"/"$baseName.mp4" -hide_banner -loglevel warning 
        else
                echo $filename
                echo $audioformat + $videoformat
                ffmpeg -i "$filename" -y -c:v libx264 -c:a aac "$destDir"/"$baseName.mp4" -hide_banner -loglevel warning 
        fi


done

if possible , check whether this code looks good.

1 Answer 1

2

Here's what I would do:

Replace for ... ; do with:

    find "$srcDir" -type f |
    while IFS= read -r filename; do
        relPath="${filename#${srcDir}}"
        relPath=$(dirname "${relPath#/}")
        tgtDir="$destDir/$relPath"
        mkdir -p "$tgtDir"

and then replace "$destDir"/"$baseName.mp4" with "$tgtDir/$baseName.mp4". Use = to test for string equality, not ==; see help test.

EDIT: shellcheck.net suggests you use ffmpeg -nostdin ... to prevent ffmpeg from swallowing stdin -- which could interfere with read, cf. link.

Sign up to request clarification or add additional context in comments.

9 Comments

works good but,on else condition the $filename strips first few characters automatically.
lets say for example, main-video/first/sub/1.mp4 is changing to n-video/first/sub/1.mp4.
Are you saying that the first 3 characters of $relPath always disappear? In that case please give an example of $srcDir and $filename.
$srcDir = sample-videos-segment/ $filename = sample-videos-segment/New/First/c5eb8d98-5d4e-4d00-8c4e-f44aac599e60.mp4
not the first 3 characters it automatically truncates, random n characters in the above case: -videos-segment/New/First/c5eb8d98-5d4e-4d00-8c4e-f44aac599e60.mp4 sample is removed
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.