1

I'm trying to convert all files in folders given by

 allFolders.txt
> head folderNames.txt
0001 
0002 
0003 
0004 
0005 
...

to a video using ffmpeg

ffmpeg version 2.2.3 Copyright (c) 2000-2014 the FFmpeg developers  built on Apr 20 2015 13:38:52 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
configuration: --prefix=/home/myUsername/usr/local --enable-nonfree --enable-gpl --enable-pic --enable-shared --enable-libx264 --disable-vaapi

According to some answers here on stackoverflow I wrote the following bash script:

#!/bin/bash
while read p; do
    cd "$p"
    ffmpeg -f concat -i "allImgNames.txt" -framerate 30 -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p output.mp4
    cd -
done < folderNames.txt

where allImgNames.txt is a text file containing all the image names.

The strange thing is that it works for a few videos but for the rest of the filelist it fails saying allImgNames.txt: No such file or directory, which is not true. I checked all paths several times. Also I can execute the ffmpeg ... command above manually without problems. I don't know what I'm doing wrong. All file / folder names are normal (no special characters). Maybe I don't understand enough about bash or ffmpeg.

mcExchange
  • 6,154
  • 12
  • 57
  • 103
  • 1
    Any spaces in file or directory names? – davejagoda Oct 31 '15 at 00:29
  • You change directory in the script, so the file `allImgNames.txt` is no longer in the *current* directory. Unless each directory you change to as a separate file with that name? – Some programmer dude Oct 31 '15 at 00:33
  • nope. What is really strange is that when I put a `echo "$p"` after `cd "$p"` in the example given above, it behaves normally when I comment the `ffmpeg` comment but it as soon as I uncomment again `ffmpeg` even the paths it prints are wrong (missing leading 0's), eg it prints `30` instead of `0030` – mcExchange Oct 31 '15 at 00:34
  • I have a text file with all image filenames in every subdirectory. That's why I can execute the `ffmpeg` command outside my bash script normally – mcExchange Oct 31 '15 at 00:35
  • With that *exact* name? Remember that filenames in POSIX environments (like Linux) is case-sensitive. – Some programmer dude Oct 31 '15 at 00:36
  • I know. But in my case both the folder names as well as the image names consist only of numbers (folders: `0001`, `0002` ... ; images: `0001.jpg`, `0002.jpg` ... – mcExchange Oct 31 '15 at 00:38
  • 1
    I mean the `allImgNames.txt` file, does it really have that casing? In all folders? And it *does* exist in *all* folders? Does it always fail on the same directories? Or seemingly random? Have you tried doing e.g. `ls allImgNames.txt` in the script instead of the `ffmpeg` command? Or instead of changing directory and `ffmpeg`, just do `ls "$p/allImgNames.txt` in the loop, if the files are missing in only some directories that will make it very obvious. – Some programmer dude Oct 31 '15 at 00:43
  • Yes they all exist and have that exact filename. I also checked your `ls` command. Everything works perfectly, except when I'm trying to call the `ffmpeg` command from that script. – mcExchange Oct 31 '15 at 10:25
  • Yes it does always fail on the same directories, although what is strange is that the folder names in `allFolders.txt` are ordered, but when I execute the script, it seems to process the folder names in a different order 0001, 0003, ... instead of 0001, 0002 ... – mcExchange Oct 31 '15 at 10:31

2 Answers2

2

Add some logic in your script to ensure that files/folders exist before something gets executed. This will help you debug your issues along the way.

If the folder paths are NOT relative, something like this would help

while read p; do
    [ -d "$p" ] && cd "$p" || echo "Folder $p not found"
    [ -f "allImgNames.txt" ] && ffmpeg -f concat -i "allImgNames.txt" -framerate 30 -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p output.mp4 || echo "$p/allImgNames.txt not found"
    [ -d "$p" ] && cd -
done < folderNames.txt
Iyad K
  • 266
  • 1
  • 8
  • This script always fails already the second folder "Folder not found". It doesn't event print "Folder $p not found" as it should. When I edit your script such that it doesn't `cd $p` and `cd -` it processes a lot of videos (800 of 3000 in total) so there was some improvement but still there seems to be something wrong. – mcExchange Oct 31 '15 at 10:53
  • OK, so the issue is somewhere in the environment. It might be FFMPG playing with the OLDPWD in some way. So instead of 'cd -', try using the party to the parent folder. Also, add an echo statement before "CD $p" to print out the variable $p. – Iyad K Nov 01 '15 at 11:27
  • Thanks. Meanwhile I could solve my problem using your answer. As I said above I was removing all `cd $p` and `cd -` statements and call the files from the parent directory instead. Then I added a line that checks whether the output video already exists and then skips that folder. Like that I could execute the same script several times and at the end got all 3000 videos converted. I will mention this hack in a answer, however I still consider this problem as unsolved, since it's not clear why ffmpeg arbitrarily fails when used in that bash script, although all paths are correct. – mcExchange Nov 01 '15 at 19:36
0

According to this post post ffmpeg indeed messes up with loops in a batch script. You have to add -nostdin as option to the ffmpeg command, otherwise ffmpeg eats some parts of subsequent folder names.
Moreover some video conversion failed due to this bug in the libx264 codec. To repair it just use this option to convert the image to a image with a even height size: -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2"

With some help of Iyad K's answer I could get my problem solved:

Here is a complete solution:

#!/bin/bash
while read p; do
    # Continue if output file already exists
    {
    if [ -f "$p/output.mp4" ]; 
    then
        echo " --> File already exists. Continue ..."
        continue
    else
        echo " --> Start processing vid ..."
    fi
    }    

    # Convert video using ffmpeg:
    # "-nostdin" prevents bashscript from messing up
    # "-vf ..." makes sure the video doesn't break for images with uneven pixel hight
    ffmpeg -f concat -i "$p/allImgNames.txt" -nostdin -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" "$p/output.mp4" 
done < folderNames.txt  

Some remarks:
Somehow the ffmpeg command seems to mess up bash scripts, e.g. some path are not printed correctly anymore, which could cause cd "$p" and cd - to fail.
What was also strange is the fact that the folders where not processed in the same sequential order given by folderNames.txt, but apparantly in some random order.

Community
  • 1
  • 1
mcExchange
  • 6,154
  • 12
  • 57
  • 103