1

I have a script that runs every 10 minutes which causes ffmpeg to run over and over and really slows it down. I'd like to only run one instance at a time so the movies will appear quicker on my website (And not crash my server).

Here is my code:

for i in MovieCategories/Category1/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done

for i in MovieCategories/Category2/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done
for i in MovieCategories/Category3/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done
for i in MovieCategories/Category4/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done

for i in MovieCategories/Category5/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done
for i in MovieCategories/Category6/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done
for i in MovieCategories/Category7/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done

for i in MovieCategories/Category8/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done
for i in MovieCategories/Category9/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done
for i in MovieCategories/Category10/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done

for i in MovieCategories/Category11/*/*.mkv;
  do name=`echo $i | cut -d'.' -f1`;
  echo $name;
  ffmpeg -n -i "$i" "${name}.mp4"; rm -v "${name}.mkv";
done

I attempted to consolidate them into one command to help a bit but for some reason it mismatched the names from different directories and failed. Overall my main goal is to only run one movie at a time. If you could help consolidate this that would be a bonus. The movies are listed as follow:

MovieCategories/

  • Category1/

    • Movie1/
      • Movie1.mp4
    • Movie2/
      • Movie2.mkv
    • Movie3/
      • Movie3.mp4
  • Category2/
    • Movie4/
      • Movie4.mp4
    • Movie5/
      • Movie5.mkv
    • Movie6/
      • Movie6.mp4

And on...

RobertW
  • 156
  • 14

3 Answers3

1

You can check to see if ffmpeg is running with something like:

#!/bin/bash
if ps aux | grep -i '[f]fmpeg' ; then
  echo "running"
else 
  echo "not running"
fi

The exit code of the ps aux command is put into $?. If it is zero, then ffmpeg is running. If it is not running, it won't be zero. Hopefully, you can adapt this script to fit your needs.

  • 3
    `ps aux | grep -i ffmpeg` will be unreliable because, depending on timing, it may match on the `grep` process. Use `ps aux | grep -i '[f]fmpeg'` (yes, it looks odd but it works) or, better yet, use `pgrep` which is designed for just this issue. – John1024 Jun 05 '19 at 00:19
  • 1
    Also, `if [[ $? ]]; then` doesn't do what you expect. `[[ $? ]]` evaluates as true for any exit code. If you must use `ps`, use `if `ps aux | grep -qi '[f]fmpeg'; then`. – John1024 Jun 05 '19 at 00:24
  • Great call John! I edited it so that the proper functionality can be achieved in an additional way. – Scott Morris Jun 05 '19 at 00:24
  • Again, correct. I corrected it so that `if [[ $? -eq 0 ]] ; then` will only be true if the most recent exit code was zero. – Scott Morris Jun 05 '19 at 00:29
  • you can get the same result in the `if ps aux | grep -i '[f]fmpeg' ; then` form. Getting the return code of the last program in the pipeline. Good luck! – shellter Jun 05 '19 at 01:03
  • @John1024 and shellter - I updated the script according to your suggestions. I also verified that the suggestions work as advertised. We should have a solid answer, now. – Scott Morris Jun 05 '19 at 04:43
  • Also "ps auxf | grep '[f]fmpeg'" is not reliable, because it could match other processes that contain the string ffmpeg somewhere, even in a path or only matches part of the command name like "ffmpegthumbnailer", that's why I would always prefer pgrep in such cases. – jottbe Jun 13 '19 at 08:38
1

You can also use pgrep to check if it is running. That's a more direct way as to run ps and pipe it's output to grep:

like this:

! pgrep ffmpeg > /dev/null && echo "not running"

Or in case you require an if statement, of course:

if ! pgrep ffmpeg ; then
    echo "not running"
fi

This would also match processes where ffmpeg appears somewhere in the process name. So it would also match processes named blahffmpegblah. The suggestion which uses "ps | grep" has a similar behavior btw. but could also match processes that include ffmpeg somewhere in the command line (including files and options passed as arguments). If you don't like this behavior, you can use the -x option:

if ! pgrep -x 'ffmpeg' ; then
    echo "not running"
fi
jottbe
  • 4,228
  • 1
  • 15
  • 31
0

One of the solutions is to concatenate video files - ffmpeg doc. There will be no any delay or any slow downs.

ffmpeg -i "concat: file1.mkv | file2.mkv | file3.mkv" -c copy output.mkv

Also there is an option to create video from a list of files - so example. By using RegEx it will be a perfect automatization.

:: Create File List
for %%i in (*.mkv) do echo file '%%i'>> video_list.txt

:: Concatenate Files
ffmpeg -f concat -safe 0 -i video_list.txt -c copy output.mkv


PS: You can perform transformations as changing resolution or the frame rate to the video, converting the video to a new format, etc. And create multiple copies of one video in the output file.

piet.t
  • 11,718
  • 21
  • 43
  • 52
Bulat
  • 720
  • 7
  • 15
  • concat protocol should only be used on file formats without a global header, like MPEG-TS. – Gyan Jun 05 '19 at 08:20
  • Can you explain why? What will it corrupt in output file? What `extradata` stands for? What does it mean in different formats? If I'll concat only mp4 files? Will it create one `global_header`? (I can ask a question on `SO`, if you want). – Bulat Jun 05 '19 at 09:39
  • How it will influence on `pts`? Can we switch off `bitstream filters`? – Bulat Jun 05 '19 at 09:45