Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFmpeg create output directory hierarchy

Tags:

ffmpeg

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?

like image 364
David Avatar asked Apr 23 '17 12:04

David


People also ask

What output files does FFmpeg support?

There are three output files specified, and for the first two, no -map options are set, so ffmpeg will select streams for these two files automatically. out1.mkv is a Matroska container file and accepts video, audio and subtitle streams, so ffmpeg will try to select one of each type.

Where does FFmpeg search for a file in Linux?

First ffmpeg searches for a file named arg .ffpreset in the directories $FFMPEG_DATADIR (if set), and $HOME/.ffmpeg, and in the datadir defined at configuration time (usually PREFIX/share/ffmpeg ) or in a ffpresets folder along the executable on win32, in that order.

How does FFmpeg select audio and video streams in Matroska?

out1.mkv is a Matroska container file and accepts video, audio and subtitle streams, so ffmpeg will try to select one of each type. For video, it will select stream 0 from B.mp4, which has the highest resolution among all the input video streams. For audio, it will select stream 3 from B.mp4, since it has the greatest number of channels.

How do I set input options in FFmpeg?

Options may be set by specifying - option value in the FFmpeg tools, or by setting the value explicitly in the device AVFormatContext options or using the libavutil/opt.h API for programmatic use. Input devices are configured elements in FFmpeg which enable accessing the data coming from a multimedia device attached to your system.


1 Answers

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
like image 96
Stephen Avatar answered Sep 27 '22 20:09

Stephen