ffmpeg two-pass in ts stream production - bash

How can I make a two-pass convert while using .ts chunks output?
I use the following command inside bash script for chunks generation (I think all variables are clear enough for understanding):
ffmpeg -i $1 -threads 1 -b:v ${selected_bitrate} -b:a ${audio_bitrate} -s ${selected_width}x${selected_height} -r ${framerate} -preset fast -level ${level} -vcodec libx264 -f ssegment -segment_list b${selected_bitrate}.m3u8 -segment_time 9 -force_key_frames "expr:gte(t,n_forced*9)" -y b${selected_bitrate}_%05d.ts
I want to try two-pass because I need to match desired bitrate more accurate. Right now when I use for example 200k bitrate for video stream, it results ~380k in ts chunks (of course without audio).

Just call the libx264 with "-pass 1" like the following:
ffmpeg -i $1 -threads 1 -ar -b:v ${selected_bitrate} -s ${selected_width}x${selected_height} -r ${framerate} -preset fast -level ${level} -vcodec libx264 -pass 1 -f null -
Then repeat your command with "-pass 2":
ffmpeg -i $1 -threads 1 -b:v ${selected_bitrate} -b:a ${audio_bitrate} -s ${selected_width}x${selected_height} -r ${framerate} -preset fast -level ${level} -vcodec libx264 -pass 2 -f ssegment -segment_list b${selected_bitrate}.m3u8 -segment_time 9 -force_key_frames "expr:gte(t,n_forced*9)" -y b${selected_bitrate}_%05d.ts
That should give you what you want.

Related

ffmpeg youtube livestream stops after a while

I'll update this question
ffmpeg -version
ffmpeg -version
ffmpeg version 4.3.1-4ubuntu1 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 10 (Ubuntu 10.2.0-9ubuntu2)
I run this command to use ffmpeg to stream to youtube ;
ffmpeg -y -threads 12 \
-loop 1 -framerate 30 -re \
-i ./1280x720.jpg \
-i ./audio.mp3 \
-video_size 1280x720 \
-vcodec libx264 -pix_fmt yuv420p \
-b:v 4500k -maxrate 5500k -bufsize 22000k \
-preset ultrafast -crf 23 -tune stillimage \
-b:a 128k -ar 44100 -ac 2 -acodec aac \
-filter_complex "dynaudnorm=f=150:g=15" \
-r 30 -g 60 \
-f flv rtmp://a.rtmp.youtube.com/live2/xxxx 2>&1 | tee _LOG
The stream is excellent for 45-53 minutes then i'll get an error like this from ffmpeg:
[flv # 0x56077027cd80] Delay between the first packet and last packet in the muxing queue is 10034000 > 10000000: forcing output
then youtube starts to say, no data being received and the stream will end, which it does.
This is the full log: http://0x0.st/-zUH.txt
Your MP3 duration is 00:49:57.42 so the stream messes up after it ends. Loop the audio with -stream_loop -1 and add -re for real-time reading of the input:
ffmpeg -y \
-loop 1 -framerate 30 -re -i ./1280x720.jpg \
-re -stream_loop -1 -i ./audio.mp3 \
-c:v libx264 -pix_fmt yuv420p \
-b:v 4500k -maxrate 5500k -bufsize 22000k \
-preset ultrafast -tune stillimage \
-b:a 128k -ar 44100 -ac 2 -c:a aac \
-filter_complex "dynaudnorm=f=150:g=15" \
-g 60 -f flv rtmp://a.rtmp.youtube.com/live2/xxxx
Alternatively, remove -re -stream_loop -1 and add the output option -shortest if you want the stream to end when the audio ends.
Unrelated changes:
No need to set -threads. Let ffmpeg auto choose.
-video_size 1280x720 is an input option for certain demuxers and does nothing in your command. Removed. Your input is already 1280x720 anyway: otherwise, see Resizing videos with ffmpeg to fit a specific size.
-b:v and -crf are mutually exclusive. In your case -b:v is being ignored. For streaming you probably want to use -b:v. Removed -crf.
You already set the frame rate with -framerate 30 so -r 30 is not needed. Removed.
Recommend using the slowest -preset that still encodes fast enough.

What ffmpeg output format (-f) do I use for two-pass encoding of mkv files

I recently backed up one of my Blu-ray movies and it is about 36 GB. Using ffmpeg to get info from the video, it is in h.264 in an mkv container. I want to shrink the file size using h.265 compression and targeting a bitrate of 4 Mbits/s so that I can stream it while I am away from my home over my Plex server. My upload speed is limited to 5 Mb/s.
Although I could easily do this with simple software, I want to learn more coding. I have found the proper ffmpeg code two do a two-pass encoding, but in all examples I have found, they use an output format of mp4 but state that "you need to specify an output format (with -f) that matches the output format you will use in pass 2." I assume my "output format" is mkv, but that does not allow my code to run. Can someone explain to me what is meant by output format and what I should be using to encode this from h264 to h265 in a mkv container?
ffmpeg -y -i input.mkv -c:v libx265 -b:v 4M -x265-params pass=1 -an -f mkv /dev/null && \ ffmpeg -i "Arrival (2016).mkv" -c:v libx265 -b:v 4M -x265-params pass=2 -c:a copy output.mkv
Also, in order to make this work on my windows PC, I am trying to learn how to edit some of the arguments to allow it to work in Powershell. I believe this is how I would do that:
(ffmpeg -y -i input.mkv -c:v libx265 -b:v 4M -x265-params pass=1 -an -f mkv NUL) -AND (^ ffmpeg -i "Arrival (2016).mkv" -c:v libx265 -b:v 4M -x265-params pass=2 -c:a copy output.mkv)
Use -f matroska. mkv is a common file extension for the matroska container format. Normally, ffmpeg uses the output filename to guess output format (e.g. *.ts -> mpegts, *.mp4 -> mp4, etc.). See output of ffmpeg -formats for a list of valid muxers and demuxers.
How to choose ffmpeg codec and container for low bandwidth video server:
You might want to download, install and use Handbrake for Windows 64-bit and WinFF to learn what settings to use.
Windows users use NUL instead of /dev/null and ^ instead of \
Non-Windows users use /dev/null instead of NUL and \ instead of ^
ffmpeg -y -i "1.mkv" -c:v libx265 -b:v 4M -pass 1 -an -f matroska NUL &&^
ffmpeg -i "1.mkv" -c:v libx265 -b:v 4M -pass 2 -c:a aac -b:a 128k "output.mkv"
rem
is the same as
ffmpeg -y -i "1.mkv" -c:v libx265 -b:v 4M -pass 1 -an -f matroska NUL && ffmpeg -i "1.mkv" -c:v libx265 -b:v 4M -pass 2 -c:a aac -b:a 128k "output.mkv"
rem
You might want to compare Constant Rate Factor (CRF) versus Two-Pass ABR and 265 versus 264. 720p in a mp4 container, H264 w/ max bitrate of 4Mbps, and AAC audio might be your best choice. CRF265 makes the smallest file.
Make a 15 second video starting at 1 minute in:
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx264 -b:v 4M -filter:v scale=1280:720 -preset slow -c:a copy -t 00:00:15 "outputSlow264720p.mp4" &&^
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx264 -b:v 4M -f matroska -c:a copy -t 00:00:15 "outputSlow264.mkv" &&^
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx265 -crf 28 -f matroska -c:a copy -t 00:00:15 "outputCRF265.mkv" &^
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx265 -b:v 4M -f matroska -c:a copy -t 00:00:15 "output4M265.mkv" &^
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx264 -preset slow -crf 22 -f matroska -c:a copy -t 00:00:15 "outputCRF264Slow.mkv" &^
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx264 -b:v 4M -f matroska -c:a copy -t 00:00:15 "output4M264.mkv"
rem
See https://trac.ffmpeg.org/wiki/Encode/H.265 These gains will be most pronounced at resolutions of 1080p and higher.
See https://trac.ffmpeg.org/wiki/Encode/H.264 CRF: This is the recommended rate control mode for most uses.
See https://programminghistorian.org/en/lessons/introduction-to-ffmpeg
See https://opensource.com/article/17/6/ffmpeg-convert-media-file-formats
See https://davidhide.com/2019/02/03/compressing-audio-with-ffmpeg-and-powershell/
See https://slhck.info/video/2017/02/24/crf-guide.html
PowerShell in one line with replacement for ^ and && : 2-pass both h265.mkv and h264.mp4 output
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx265 -b:v 4M -pass 1 -an -f matroska -t 00:00:15 NUL; if($?) {ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx265 -b:v 4M -pass 2 -c:a copy -t 00:00:15 "output.mkv"}
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx264 -b:v 4M -pass 1 -an -f mp4 -t 00:00:15 NUL; if($?) {ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx264 -b:v 4M -pass 2 -c:a copy -t 00:00:15 "output.mp4"}
rem
PowerShell in two lines: 720p h264.mp4 2-pass output
ffmpeg -ss 00:01:00 -i "1.mkv" -c:v libx264 -b:v 4M -filter:v scale=1280:720 -preset slow -c:a copy -t 00:00:15 -pass 1 output.mp4
ffmpeg -ss 00:01:00 -y -i "1.mkv" -c:v libx264 -b:v 4M -filter:v scale=1280:720 -preset slow -c:a copy -t 00:00:15 -pass 2 output.mp4
rem
Preset - See https://trac.ffmpeg.org/wiki/Encode/H.264
A preset is a collection of options that will provide a certain encoding speed to compression ratio. A slower preset will provide better compression (compression is quality per filesize). This means that, for example, if you target a certain file size or constant bit rate, you will achieve better quality with a slower preset. Similarly, for constant quality encoding, you will simply save bitrate by choosing a slower preset.
Use the slowest preset that you have patience for. The available presets in descending order of speed are:
ultrafast
superfast
veryfast
faster
fast
medium – default preset
slow
slower
veryslow

FFMPEG image not updating

THE INPUT FILES
An overlay image that has is being updated every 5 seconds by a Python script
A small MP4 file that will be looped by a concat input
An MP3 file as audio source
THE COMMAND (UPDATED)
This is the command I'm currently using to combine and stream the inputs.
ffmpeg -re -i music.mp3 -f concat -i videoincludes.txt
-r 1 -loop 1 -f image2 -i overlay.png
-c:v libx264 -c:a aac -shortest -crf 23 -pix_fmt yuv420p
-maxrate 2500k -bufsize 2500k -preset ultrafast -r 30 -g 60 -b:v 2000k -b:a 192k -ar 44100
-filter_complex "[1:v][2:v] overlay=0:0" -map 0:a -strict -2
-f flv rtmp://a.rtmp.youtube.com/live2/{key}
Als tried using -framerate 1 instead of -r 1
THE ISSUE
So the issue is that the image doesn't always update. Sometimes it does update every couple seconds at the start but it stops updating after 10-20 seconds without any difference in log output and sometimes it just doesn't update.
I can however confirm that the image is being updated by the Python script but FFmpeg is just not picking this up.
I read setting the input format of the image to image2 should allow it to update so I am not sure what is wrong or what I can do to improve it.
I'm working on the same task, and finally, I think, I found the answer.
Because streams different from each other we must reset their timestamps with setpts=PTS-STARTPTS to have them begin in the same zero timestamp . And, also, try to use image2pipe instead of image2.
This is your code with timestamp reset:
ffmpeg -re -i music.mp3 -f concat -i videoincludes.txt
-r 1 -loop 1 -f image2pipe -i overlay.png
-c:v libx264 -c:a aac -shortest -crf 23 -pix_fmt yuv420p
-maxrate 2500k -bufsize 2500k -preset ultrafast -r 30 -g 60 -b:v 2000k -b:a 192k -ar 44100
-filter_complex "[1:v]setpts=PTS-STARTPTS[out_main]; [2:v]setpts=PTS-STARTPTS[out_overlay]; [out_main][out_overlay]overlay=0:0" -map 0:a -strict -2
-f flv rtmp://a.rtmp.youtube.com/live2/{key}
p.s and I think, there is no need in -r or -framerate anymore

FFMPEG stream_loop with Overlay

Doing live streaming using the FFMPEG.
I want to do endless loop on input stream.
Use the -stream_loop -1 option, but not work. How can I do it?
-re -stream_loop -1 -i "Background.mp4" -f image2pipe -i pipe:0 -filter_complex "[0:v][1:v] overlay=0:0" -acodec aac -ar 44100 -b:a 128k -pix_fmt yuv420p -profile:v main -s 1280x720 -bufsize 8000k -maxrate 4000k -deinterlace -vcodec libx264 -preset veryfast -g 30 -r 30 -f flv "URL"
My suggestion is that you use a bash script to loop the script so it repeats itself forever. To do this you create a file and name it for example: Loop.sh
Open the file and format it like this:
#!/bin/bash
while true
do
ffmpeg "Background.mp4" -f image2pipe -i pipe:0 -filter_complex "[0:v][1:v] overlay=0:0" -acodec aac -ar 44100 -b:a 128k -pix_fmt yuv420p -profile:v main -s 1280x720 -bufsize 8000k -maxrate 4000k -deinterlace -vcodec libx264 -preset veryfast -g 30 -r 30 -f flv "URL"
done
Save the file and using the terminal (assuming you're using linux or Mac) make it executable. cd into the directory and use command
sudo chmod +x Loop.sh
Now you can run the script by simply typing ./Loop.sh and it will execute forever (until you stop it).
while true to equal anything like while 1=1 or any combinations of variables that will result true.

FFmpeg Live Stream - Loop Video?

I am trying to stream a video loop to justin.tv using FFmpeg? I have managed to loop an image sequence and combine it with line in audio:
ffmpeg -loop 1 -i imageSequence%04d.jpg -f alsa -ac 2 -ar 22050 -ab 64k \
-i pulse -acodec adpcm_swf -r 10 -vcodec flv \
-f flv rtmp://live.justin.tv/app/<yourStreamKeyHere>
Is it possible to do this with a video file?
Definitely possible. In the recent versions of ffmpeg they have added a -stream_loop flag that allows you to loop the input as many times as required.
The gotcha is that if you don't regenerate the pts from the source, ffmpeg will drop frames after the first loop (as the timestamp will suddenly go back in time). To avoid this, you need to tell ffmpeg to generate the pts so you get an increasing timestamp between loops. This is done with the +genpts call (it has to be before the -i arg).
Here's an example ffmpeg call (replace $F with your input file). This example generates two output streams and the -stream_loop -1 argument tells ffmpeg to continuously loop the input. The output in this case is for a similar stream broadcast ingest (MetaCDN), adjust accordingly to your requirements.
ffmpeg -threads 2 -re -fflags +genpts -stream_loop -1 -i $F \
-s 640x360 -ac 2 -f flv -vcodec libx264 -profile:v baseline -b:v 600k -maxrate 600k -bufsize 600k -r 24 -ar 44100 -g 48 -c:a libfdk_aac -b:a 64k "rtmp://publish.live.metacdn.com/2050C7/dfsdfsd/lowquality_664?hello&adbe-live-event=lowquality_" \
-s 1920x1080 -ac 2 -f flv -vcodec libx264 -profile:v baseline -b:v 2000k -maxrate 2000k -bufsize 2000k -r 24 -ar 44100 -g 48 -c:a libfdk_aac -b:a 64k "rtmp://publish.live.metacdn.com/2050C7/dfsdfsd/highquality_2064?mate&adbe-live-event=highquality_"
Sinclair Media has found a solution by using the lavfi filter and appending :loop=0 to the file name :
This is untested:
ffmpeg -f lavfi -re -i movie=StreamTest.avi:loop=0 \
-acodec libfaac -b:a 64k -pix_fmt yuv420p -vcodec libx264 \
-x264opts level=41 -r 25 -profile:v baseline -b:v 1500k \
-maxrate 2000k -force_key_frames 50 -s 640×360 -map 0 -flags \
-global_header -f segment -segment_list index_1500.m3u8 \
-segment_time 10 -segment_format mpeg_ts \
-segment_list_type m3u8 segmented.ts
But it should create a local "index_1500.m3u8" file that streams the video in "StreamTest.avi".
I just reuse the Rob's answers with a few of modifications in order to provide a file to live streaming
ffmpeg -threads 2 -re -fflags +genpts -stream_loop -1 -i gvf.mp4 -c copy -f mpegts -mpegts_service_id 102 -metadata service_name=My_channel -metadata service_provider=My_Self -max_interleave_delta 0 -use_wallclock_as_timestamps 1 -flush_packets 1 "udp://233.0.0.1:1001?localaddr=10.60.4.237&pkt_size=188"

Resources