FFmpeg create output directory hierarchy

10,609

Nope, FFmpeg can't do that 🤬

We can add a few lines to the top of your record.sh script to create the directory for you, though.

#!/bin/sh

BASEDIRECTORY = /raid1/homes/share/public/recordings/queue/bedroom

YEAR=$(date +"%Y");
MONTH=$(date +"%m");
DAY=$(date +"%d");

# Create a directory tree for the day 
# using the current year, month, and day
mkdir -p $BASEDIRECTORY/$YEAR/$MONTH/$DAY

# Start FFmpeg hourly recordings
ffmpeg -stimeout 600\
 -rtsp_transport udp \
 -i rtsp://192.168.1.240/unicast \
 -c copy \
 -map 0:0 \
 -f segment \
 -segment_time 3600 \
 -segment_wrap 100 \
 -segment_format mov \
 -strftime 1 \
 -reset_timestamps 1 \
 "$BASEDIRECTORY/$YEAR/$MONTH/$DAY/%H-%M.mp4"

Now we just need record.sh to restart overnight to create a new folder for the $DAY. That sounds like a perfect job for cron: How to write a cron that will run a script every day at midnight?

Note: this script now requires root privilege so if you're getting the error below and cron isn't working, make sure you're typing sudo ./record.sh while testing and install your crontab as the root user like this: sudo crotab -u root -e, as @dashesy points out in his comment.

This is because mkdir with the -p or --parent option requires root privilege and if the directory isn't there FFmpeg will throw this error:

Failed to open segment '/raid1/homes/share/public/recordings/queue/bedroom/2019/01/31/10-37.mp4'
Could not write header for output file #0 (incorrect codec parameters ?): No such file or directory
Share:
10,609

Related videos on Youtube

David
Author by

David

Updated on June 24, 2022

Comments

  • David
    David about 2 years

    Recently bought an ip-cam which outputs a RTSP stream. I'm using the segment option of FFmpeg to create 60 minute long recordings.

    I want FFmpeg to write the files to a directory based on Year/Month/Date, and write to a file Hour-Minute.mp4 For example: /raid1/homes/share/public/recordings/queue/bedroom/2017/04/23/13-05.mp4 for a recording started on 23 april 2017, 13:05.

    Unfortunately FFmpeg seems to not create the directory hierarchy. FFmpeg quits since the directory can not be found.

    Input #0, rtsp, from 'rtsp://192.168.1.240/unicast':
      Metadata:
        title           : LIVE555 Streaming Media v2014.07.04
        comment         : LIVE555 Streaming Media v2014.07.04
      Duration: N/A, start: 0.000750, bitrate: N/A
        Stream #0:0: Video: h264 (High), yuv420p, 1920x1080, 90k tbr, 90k tbn, 180k tbc
        Stream #0:1: Audio: pcm_alaw, 8000 Hz, 1 channels, s16, 64 kb/s
    [segment @ 0x2557300] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
    [segment @ 0x2557300] Failed to open segment '/raid1/homes/share/public/recordings/queue/bedroom/2017/04/23/14-19.mp4'
    Output #0, segment, to '/raid1/homes/share/public/recordings/queue/bedroom/%Y/%m/%d/%H-%M.mp4':
      Metadata:
        title           : LIVE555 Streaming Media v2014.07.04
        comment         : LIVE555 Streaming Media v2014.07.04
        encoder         : Lavf57.41.100
        Stream #0:0: Video: h264, yuv420p, 1920x1080, q=2-31, 90k tbr, 90k tbn, 90k tbc
    Stream mapping:
      Stream #0:0 -> #0:0 (copy)
    Could not write header for output file #0 (incorrect codec parameters ?): No such file or directory
    

    record.sh is as follows:

    #!/bin/sh
    ffmpeg -stimeout 600\
     -rtsp_transport udp \
     -i rtsp://192.168.1.240/unicast \
     -c copy \
     -map 0:0 \
     -f segment \
     -segment_time 3600 \
     -segment_wrap 100 \
     -segment_format mov \
     -strftime 1 \
     -reset_timestamps 1 \
     "/raid1/homes/share/public/recordings/queue/bedroom/%Y/%m/%d/%H-%M.mp4"
    

    I've tried not using a directory hierachy: "/raid1/homes/share/public/recordings/queue/bedroom/%Y-%m-%d_%H-%M.mp4". This works fine.

    $ ffmpeg -version
    ffmpeg version N-80901-gfebc862 Copyright (c) 2000-2016 the FFmpeg developers
    built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
    configuration: --extra-libs=-ldl --prefix=/opt/ffmpeg --mandir=/usr/share/man --enable-avresample --disable-debug --enable-nonfree --enable-gpl --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb --disable-decoder=amrnb --disable-decoder=amrwb --enable-libpulse --enable-libfreetype --enable-gnutls --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-libvorbis --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libspeex --enable-libass --enable-avisynth --enable-libsoxr --enable-libxvid --enable-libvidstab
    libavutil      55. 28.100 / 55. 28.100
    libavcodec     57. 48.101 / 57. 48.101
    libavformat    57. 41.100 / 57. 41.100
    libavdevice    57.  0.102 / 57.  0.102
    libavfilter     6. 47.100 /  6. 47.100
    libavresample   3.  0.  0 /  3.  0.  0
    libswscale      4.  1.100 /  4.  1.100
    libswresample   2.  1.100 /  2.  1.100
    libpostproc    54.  0.100 / 54.  0.100
    

    Can FFmpeg create output directories on the go?

  • Stephen
    Stephen almost 5 years
    Update: for HLS use -strftime 1 with -strftime_mkdir 1 and -hls_segment_filename '%Y/%m/%d/%H-%M.ts'. FFmpeg will create the directory structure. See the FFmpeg documentation here: ffmpeg.org/ffmpeg-formats.html#Options-5
  • john ktejik
    john ktejik over 4 years
    HLS? Whats that? Can it do it or not?
  • Travis Britz
    Travis Britz over 4 years
    None of this actually requires root, these errors are just because the script was run as root (either in the root user's crontab or run with sudo), so it created directories while running under the root user (therefore owned by root). As long as the script is added to a normal user's crontab and the directories are owned by that user, you can run this script as that user (without root/sudo).