Issue restreaming with ffmpeg if source/destination drops - ffmpeg

I am using the following command to restream a video stream to another server, but if the source/destination momentarily drops, ffmpeg gives up.
ffmpeg \
-i http://source_stream_ip:port \
-reconnect_at_eof 1 \
-reconnect_streamed 1 \
-y \
-shortest \
-c: libx264 \
-crf:v 22 \
-preset:v fast \
-pix_fmt yuv420p \
-x264opts keyint=10:no-scenecut=1 \
-maxrate:v 256k \
-bufsize:v 512k \
-c:a aac \
-ac 2 \
-b:a 96k \
-maxrate:a 96k \
-bufsize:a 192k \
-f flv \
rtmp://destination_stream_ip:port
I've tried this as a batch command, but it also eventually gives up.
#!/bin/bash
while :
do
ffmpeg \
-i http://source_stream_ip:port \
-reconnect_at_eof 1 \
-reconnect_streamed 1 \
-y \
-shortest \
-c: libx264 \
-crf:v 22 \
-preset:v fast \
-pix_fmt yuv420p \
-x264opts keyint=10:no-scenecut=1 \
-maxrate:v 256k \
-bufsize:v 512k \
-c:a aac \
-ac 2 \
-b:a 96k \
-maxrate:a 96k \
-bufsize:a 192k \
-f flv \
rtmp://destination_stream_ip:port
done
Could anyone recommend an improvement to doing this or even another way of doing this even without ffmpeg by using another command line tool? At the moment it is too unreliable to use on a permanent basis.

Try to add:
-reconnect_on_network_error 1 -reconnect_on_http_error 1

The -reconnect_at_eof and -reconnect_streamed options should be put before -i SOURCE:
ffmpeg \
-reconnect_at_eof 1 \
-reconnect_streamed 1 \
-i http://source_stream_ip:port \
...

Related

ffmpeg: "Warning: data is not aligned! This can lead to a speed loss"

Using ffmpeg, I get the warning
Warning: data is not aligned! This can lead to a speed loss
In my case, speed an cpu consuption matter.
I found two discussions about that. Both are quite old:
https://ffmpeg.org/pipermail/ffmpeg-user/2017-October/037501.html#:~:text=This%20can%20lead%20to%20a%20speedloss.%20%3E,(i.e.%20may%20be%20slower).
https://superuser.com/questions/728795/new-ffmpeg-swscaler-0xa314080-warning-data-is-not-aligned-this-can-lead
Every cropping and also every rescaling process as well as the placement of the pip is a multiple of 16 in my case. Also the input (2560x1920) meets that criteria.
Here is the code:
/usr/bin/ffmpeg \
-fflags nobuffer \
-rtsp_transport tcp \
-i 'rtsp://XXX' \
-timeout 6000000 \
-r 0.5 \
-copyts \
-an \
-hls_flags delete_segments+append_list \
-filter_complex \
"[0:v]split=2[a][b];\
[a]scale=768:576[c];\
[b]crop=256:272:1008:608,scale=320:240[d];\
[d]pad=w=16+iw:h=16+ih:x=16:y=16:color=#ff78a8[e];\
[c][e]overlay=0+16:0+32[f]" \
-map "[f]" \
-c:v libx264 -preset veryfast -r 0.5 -g 0.5 -sc_threshold 0 \
-f segment \
-segment_list_flags live \
-segment_time 3 \
-segment_list_size 3 \
-segment_format mpegts \
-segment_list_type m3u8 \
-segment_list_entry_prefix /XXX/stream/ \
-segment_list /var/www/video_streaming/XXX/index_4.m3u8 \
/var/www/video_streaming/XXX/stream/s4_%d.ts
Any idea how to fix this?

Change ffmpeg input while streaming

Is there a way to change ffmpeg input while streaming to rtmp?
I have this bash script
#! /bin/bash
VBR="1500k"
FPS="24"
QUAL="superfast"
RTMP_URL="rtmp://live.live/live"
KEY="xxxxxxxxxxxxxxxxxxxxx"
VIDEO_SOURCE="video.mp4"
AUDIO_SOURCE="song.mp3"
NP_SOURCE="song.txt"
FONT="font.ttf"
ffmpeg \
-re -f lavfi -i "movie=filename=$VIDEO_SOURCE:loop=0, setpts=N/(FRAME_RATE*TB)" \
-thread_queue_size 512 -i "$AUDIO_SOURCE" \
-map 0:v:0 -map 1:a:0 \
-map_metadata:g 1:g \
-vf drawtext="fontsize=25: fontfile=$FONT: \
box=1: boxcolor=black#0.5: boxborderw=20: \
textfile=$NP_SOURCE: reload=1: fontcolor=white#0.8: x=50: y=50" \
-vcodec libx264 -pix_fmt yuv420p -preset $QUAL -r $FPS -g $(($FPS * 2)) -b:v $VBR \
-acodec libmp3lame -ar 44100 -threads 6 -qscale:v 3 -b:a 320000 -bufsize 512k \
-f flv "$RTMP_URL/$KEY"
What i want to do is to be able to change VIDEO_SOURCE on the fly, i was thinking if it's possible to make the input a directory then change the video in that directory on the fly, i'm new to dealing with scripts so i don't know how to do that
This is a complete guess, based on what little I know about how ffmpeg handles interactive input:
while :; do
ffmpeg \
-re -f lavfi -i "movie=filename=$VIDEO_SOURCE:loop=0, setpts=N/(FRAME_RATE*TB)" \
-thread_queue_size 512 -i "$AUDIO_SOURCE" \
-map 0:v:0 -map 1:a:0 \
-map_metadata:g 1:g \
-vf drawtext="fontsize=25: fontfile=$FONT: \
box=1: boxcolor=black#0.5: boxborderw=20: \
textfile=$NP_SOURCE: reload=1: fontcolor=white#0.8: x=50: y=50" \
-vcodec libx264 -pix_fmt yuv420p -preset $QUAL -r $FPS -g $(($FPS * 2)) -b:v $VBR \
-acodec libmp3lame -ar 44100 -threads 6 -qscale:v 3 -b:a 320000 -bufsize 512k \
-f flv "$RTMP_URL/$KEY"
read -p "Next movie?" VIDEO_SOURCE
[ "$VIDEO_SOURCE" = q ] && break
done
ffmpeg should(?) exit if you send q to standard input. Your script will then prompt you for a new value for VIDEO_SOURCE. If you type q again, the loop exits. Otherwise, it restarts ffmpeg with the new video source file.
If this works, you can perhaps adapt it for something closer to your needs.

How to continuously output screenshots while also outputting hls with ffmpeg

So I have the following process of ingesting rtsp and output hls.
ffmpeg -fflags nobuffer \
-rtsp_transport udp \
-i rtsp://<source>/ \
-vsync 0 \
-copyts \
-vcodec copy \
-movflags frag_keyframe+empty_moov \
-an \
-hls_flags delete_segments \
-f segment \
-segment_list_flags live \
-segment_time 1 \
-segment_list_size 5 \
-segment_format mpegts \
-segment_list streaming.m3u8 \
-segment_list_type m3u8 \
-segment_list_entry_prefix ./ \
%d.ts
and I want to also output screenshots from the stream at some fixed frequency. Say every second.
I've tried a variety of options including
-vframes 1 -q:v 10 capture.jpeg
and its not working.
Any suggestions?
ffmpeg -fflags nobuffer \
-rtsp_transport udp \
-i rtsp://<source>/ \
-vsync 0 \
-copyts \
-vcodec copy \
-movflags frag_keyframe+empty_moov \
-an \
-hls_flags delete_segments \
-f segment \
-segment_list_flags live \
-segment_time 1 \
-segment_list_size 5 \
-segment_format mpegts \
-segment_list streaming.m3u8 \
-segment_list_type m3u8 \
-segment_list_entry_prefix ./ \
%d.ts \
-q:v 10 -vf fps=1 output_%03d.jpg

Ffmpeg - Create a HLS video with different versions and creating a master playlist

I have this ffmpeg command in order to create an HLS video with four versions with different quality features, but I don't manage it creates the .m3u8 playlist. I have added at the end of the command the control -master_pl_name, but it doesn't work.
Can someone help me to create the command I want?
ffmpeg -hide_banner -y \
-i "MySourceVideo.mp4" \
-vf scale=w=640:h=360:force_original_aspect_ratio=decrease \
-c:a aac \
-ar 48000 \
-c:v h264 \
-profile:v main \
-crf 20 \
-sc_threshold 0 \
-g 48 \
-keyint_min 48 \
-hls_time 4 \
-hls_key_info_file "MyKey.keyinfo" \
-hls_playlist_type vod \
-b:v 800k \
-maxrate 856k \
-bufsize 1200k \
-b:a 96k \
-hls_segment_filename "MyNewVideo_version_360p_%03d.ts" \
"MyNewVideo_360p.m3u8" \
\
-vf scale=w=842:h=480:force_original_aspect_ratio=decrease \
-c:a aac \
-ar 48000 \
-c:v h264 \
-profile:v main \
-crf 20 \
-sc_threshold 0 \
-g 48 -keyint_min 48 \
-hls_time 4 \
-hls_key_info_file "MyKey.keyinfo" \
-hls_playlist_type vod \
-b:v 1400k \
-maxrate 1498k \
-bufsize 2100k \
-b:a 128k \
-hls_segment_filename "MyNewVideo_version_480p_%03d.ts" \
"MyNewVideo_480p.m3u8" \
\
-vf scale=w=1280:h=720:force_original_aspect_ratio=decrease \
-c:a aac \
-ar 48000 \
-c:v h264 \
-profile:v main \
-crf 20 \
-sc_threshold 0 \
-g 48 \
-keyint_min 48 \
-hls_time 4 \
-hls_key_info_file "MyKey.keyinfo" \
-hls_playlist_type vod \
-b:v 2800k \
-maxrate 2996k \
-bufsize 4200k \
-b:a 128k \
-hls_segment_filename "MyNewVideo_version_720p_%03d.ts" \
"MyNewVideo_720p.m3u8" \
\
-vf scale=w=1920:h=1080:force_original_aspect_ratio=decrease \
-c:a aac \
-ar 48000 \
-c:v h264 \
-profile:v main \
-crf 20 \
-sc_threshold 0 \
-g 48 \
-keyint_min 48 \
-hls_time 4 \
-hls_key_info_file "MyKey.keyinfo" \
-hls_playlist_type vod \
-b:v 5000k \
-maxrate 5350k \
-bufsize 7500k \
-b:a 192k \
-hls_segment_filename "MyNewVideo_version_1080p_%03d.ts" \
"MyNewVideo_1080p.m3u8" \
\
-master_pl_name "MyNewVideo_index.m3u8"
I'm working on a similar problem and am equally surprised by the seeming lack of resources about this.
Anyway, I think you'll be able to get a step further if you add a single output file name after -master_pl_name "MyNewVideo_index.m3u8" output_%v.m3u8. I would then recommend removing the individual names for the quality streams, otherwise FFmpeg will create them twice.
It's possible you'll then have other issues, as I am, but that should solve your first problem.

How to use FFmpeg to record multiple screens on MacOS?

I wanted to record multiple screens simultaneously on MacOS and store them in a video file.Same as the screenshot below.
I found a command to do this, but need to know the size of each screen.
ffmpeg \
-f avfoundation -pix_fmt uyvy422 -i 1 \
-f avfoundation -pix_fmt uyvy422 -i 2 \
-pix_fmt yuv420p -r 30 -preset ultrafast -b:v 5000k -t 15 \
-filter_complex \
"nullsrc=size=3286x1080 [background]; \
[0:v] setpts=PTS-STARTPTS [left]; \
[1:v] setpts=PTS-STARTPTS [right]; \
[background][left] overlay=shortest=1 [background+left]; \
[background+left][right] overlay=shortest=1:x=1366 [left+right]" \
-map [left+right] out.mp4 -y
Is there a way to record a screen without knowing the size of each screen?
You can do it using the new xstack filter.
Use
ffmpeg \
-f avfoundation -pix_fmt uyvy422 -i 1 \
-f avfoundation -pix_fmt uyvy422 -i 2 \
-filter_complex \
[0:v] setpts=PTS-STARTPTS [left]; \
[1:v] setpts=PTS-STARTPTS [right]; \
[left][right] xstack=inputs=2:layout=0_0|w0_0 [left+right]" \
-map [left+right] -pix_fmt yuv420p -r 30 -preset ultrafast -b:v 5000k -t 15 \ out.mp4 -y
Get the latest dated build from https://ffmpeg.zeranoe.com/builds/macos64/static/

Resources