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
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.