When I run
ffmpeg -f concat -i resizedvideolist.txt -c copy concatenated_time.mp4 2>&1
it concatenates all the videos in the txt, but there is one video around halfway through that get glitched out. The audio just doesn't play for that video, but then starts playing on the next video, so it has been delayed. Then somewhere the audio managed to catch up and gets back in sync. Seems like some major corruption going on here.
I do not know how to fix this as the codec is the same as all the other vidoes, H.264, it is an mp4 like the others. The individual video file runs fine as it is, and it already is in the same timescale, because before this ffmpeg command, I ran
ffmpeg -i ./tempDownloadedMemes/$videoFileName -filter_complex 'scale=1080:-1,pad=1080:1080:(ow-iw)/2:(oh-ih)/2:0x2F2F2F' -video_track_timescale 15360 ./resizedVideos/resized_videoFileName 2>&1
To be honest I don't even know what timescale is, but I read that it needs to be the same for it to work. I deleted the video from the list, tried this same command, and the problem was gone at the same time in the video that it would have appeared. It seems like it is something to do with that one file itself. Any known issues/workarounds on concat bugs? This is very important to me. Thanks.
Related
I found the following command line to batch-trim videos in a folder, however it delays the sound of all the videos by a few seconds (sound comes after the video):
for file in /path/to/folder/*.mp4; do ffmpeg -i "$file" -ss 00:00:08 -c copy -avoid_negative_ts 1 "${file%.*}_trimmed.mp4"; done
These are the alternatives I found, however none of them solve the problem:
for file in /path/to/folder/*.mp4; do ffmpeg -i "$file" -itsoffset -0.5 -ss 8 -c:v copy -c:a copy "${file%.*}_trimmed.mp4"; done
for file in /path/to/folder/*.mp4; do ffmpeg -i "$file" -ss 8 -async 1 -c:v copy -c:a copy "${file%.*}_trimmed.mp4"; done
for file in /path/to/folder/*.mp4; do ffmpeg -i "$file" -ss 8 -map 0:v -map 0:a -c:v copy -c:a copy "${file%.*}_trimmed.mp4"; done
I have a hard time finding by how much time the sound is delayed.
My questions:
what would be the command line to batch-trim the beginning of all the videos in a folder with the sound properly "aligned" to the video?
in other words, can't the sound be by default trimmed by as much as the video in the first place? If yes, how?
System used:
macOS Ventura (13.1, Intel)
Shell and version: zsh 5.8.1 (x86_64-apple-darwin22.0)
ffmpeg version 5.0 built with Apple clang version 13.0.0 (clang-1300.0.29.30)
from the FFMPEG(1) manual page:
-ss position (input/output)
When used as an input option (before "-i"), seeks in this input
file to position. Note that in most formats it is not possible
to seek exactly, so ffmpeg will seek to the closest seek point
before position. When transcoding and -accurate_seek is enabled
(the default), this extra segment between the seek point and
position will be decoded and discarded. When doing stream copy
or when -noaccurate_seek is used, it will be preserved.
When used as an output option (before an output url), decodes but
discards input until the timestamps reach position.
position must be a time duration specification, see the Time
duration section in the ffmpeg-utils(1) manual.
(quoted under license, For details about the authorship, see the Git history of the project (git://source.ffmpeg.org/ffmpeg), e.g. by typing the command git log in the FFmpeg source directory, or browsing the online repository at http://source.ffmpeg.org.)
So first of all I would not be astonished that something is out of sync as it is documented and also reasonable.
As you're doing a stream copy (and not transcoding) the "overlap" will be preserved and from your description this leads to the async.
If you can easily reproduce with a single file I'd try to tweak with command line switch(es). E.g. if accurate seek can be used with copy as you perhaps don't want to re-encode and if it helps with the sync already. I'd still keep it in a file so that I can have it under version control.
This also might depend on the seek points in the original material, therefore I'd also test if re-encoding (transcoding) can help and with which options. Getting results with that can help to decide on the concrete material which way is to be favored.
When that has been decided, increase the batch size and check the output if its still as expected as with the smaller test. Then rinse and repeat until you get your wanted results.
The zsh shell scripting is helping you to formulate the command as they can become complex and you can write them down in a file. It also makes it easier for batch handling. Strictly speaking about what you ask for, this is purely about ffmpeg and technically the zsh shell scripting is unrelated to it. Just saying so it is easier to keep different issue apart (if you're later on missing files, it is likely a flaw in the scripting or error handling in the script for example).
I need to convert an SEC file into any video format that I can share and/or upload to Youtube. MP4, etc.
I'm a complete newbie at all things terminal. I've tried:
ffmpeg -i video.sec video.mp4
ffmpeg -i video.sec -bsf:v h264_mp4toannexb -c:v copy video.avi
ffmpeg -i video.sec -b 256k -vcodec h264 -acodec aac video.mp4
I don't understand what any of these mean, they're just examples I found online. However, whatever I try returns this error:
Invalid data found when processing input
Any thoughts? Thanks!
I had to add the following option so it would skip the SEC's custom header.
-skip_initial_bytes 48
i know this is old, but i was trying to figure this out as well, what ended up finally working for me was this command.
./ffmpeg -f h264 -i INPUT.sec -filter:v "setpts=4*PTS" OUTPUT.avi
the -f h264 was the part i was missing. and the -filter:v "setpts=4*PTS" part is to slow it back down to the original speed. you can also change the .avi at the end to whichever format works best for you.
i hope this helps someone out :)
OK, just to clear up some recent threads…
The Samsung DVR used here was an SRD-440. RB kindly sent me a file to test and he sent me a .BU file with an associated .db2 file. This was a bit of a surprise as in all older Samsung DVR’s, the .bu files can only be played back in the DVR. I mentioned this here, https://spreadys.wordpress.com/2014/07/21/ifsec-samsung-exports/
It appears that Samsung have caught on, and the BU file is now playable due to it being a H264/AVC Stream conforming to a standard profile. I have updated the IFSEC Post mentioned above to highlight this change.
Back to RB’s stream and the challenge was to get these files viewable in WMV format. They were all field based, at 704×288.
The speed of playback is controlled by the Samsung software, using the .db2 file. As such, the metadata and timing information in the video stream was wrong. This caused speed issues and then quality issues when attempting to correct this.
As a result, I found it necessary to force an input rate and generate a new Presentation Time Stamp BEFORE the input file.
The following FFmpeg string did the job…
ffmpeg -r 12 -fflags genpts -i FILE.bu -vf scale=704:528 -sws_flags lanczos -q:v 2 FILE.wmv
Remember, this is for preview – analysis would be completed differently due to the scaling, the interpolation method, and the WMV compression!
As its likely that RB may have quite a few .bu files in a folder, I placed this into a batch file to transcode the whole lot within a few minutes… more on batch files coming in a new post soon!
https://spreadys.wordpress.com/2014/07/21/ifsec-samsung-exports/
or
ffmpeg -i (name of file).sec (name of final file).mp4
ffmpeg -i (name of file).sec -filter:v "setpts=3.3*PTS" (name of final_file).mp4
How my stream is working right now:
Input:
Switcher program that captures the camera and screen shots and make a different layouts. One of the windows from the software is the one used as Input in the ffmpeg command line.
Output:
- Facebook (example)
- Youtube (example)
At the beginning, i thought that maybe could be better create two different ffmpeg processes to stream independently to each output. The problem was it uses too much CPU.
The answer for it, was to encode one time and copy it to different outputs. Ok, great, it solves the problem, but what if one of the output fails? Both fail.
I'm trying to make one encoding to two outputs and if one of these outputs is not available, the other keep going well.
Anybody have any idea to solve it?
Thanks!
I found the solution following what #LordNeckbeard said.
Here is a sample code to:
Save a local file
Stream to your server
Stream to Facebook server
Every stream is independent from the other and will try to recover itself independently every one second if something happened like internet connection–will save locally and try to recover when internet access came back–or destination server is not available yet and when it came back it will restart the streaming process):
-i ... -f tee "[onfail=ignore]'C:\Users\blablabla.mp4'|
[f=fifo:fifo_format=flv:drop_pkts_on_overflow=1:attempt_recovery=1:recovery_wait_time=1]rtmp://yourServer...|
[f=fifo:fifo_format=flv:drop_pkts_on_overflow=1:attempt_recovery=1:recovery_wait_time=1]"rtmp://facebook..."
Example using the tee muxer with the onfail option and also output a local file:
ffmpeg -i input -map 0 -c:v libx264 -c:a aac -maxrate 1000k -bufsize 2000k -g 50 -f tee "[f=flv:onfail=ignore]rtmp://facebook|[f=flv:onfail=ignore]rtmp://youtube|[f=segment:strftime=1:segment_time=60]local_%F_%H-%M-%S.mkv"
Also see:
FFmpeg Documentation: tee muxer
FFmpeg Documentation: segment muxer
FFmpeg Wiki: Encoding for Streaming Sites
I've used the ffmpeg command line shown in this question to split MKV files perfectly for a long time. Now i have some MP4 files that i'd like to split and at first it seemed to work, but every subsequent segment after the first has the audio not synced! And by several seconds.
I've tried forcing keyframes (advice I found on some other sites) and that didn't help.
I tried a different program entirely (Avidemux) and it was able to split the file with proper output, but it was a LOT slower, taking upwards of 3 minutes vs less than 2 seconds with ffmpeg. With Avidemux I was able to determine the exact position of the i-frame where I wanted to split, so thinking perhaps that was the syncing problem I tried that exact position (ie. 00:12:17.111 instead of 00:12:16 or whatever) but that didn't help either.
Is there an option I'm missing with ffmpeg to get it to properly sync audio to the video when splitting?
I'm not sure I understand WHY, but the issue was order of parameters.
In the linked example, the command is as follows:
ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi
Of course, I'm using mp4 instead of avi, but otherwise I was entering the command exactly as above and (with mp4) I was getting an out-of-sync audio result. I accidentally stumpled onto this "fix"... if I instead enter the command thusly:
ffmpeg -ss 00:30:00 -i input.mp4 -vcodec copy -acodec copy -t 00:30:00 output2.mp4
I don't get the sync issues. Why? No idea. But it works. I've tried it a few times to confirm... making only that order of parameters change corrects the issue.
ffmpeg handles RTMP streaming as input or output, and it's working well.
I want to stream some videos (a dynamic playlist managed by a python script) to a RTMP server, and i'm currently doing something quite simple: streaming my videos one by one with FFMPEG to the RTMP server, however this causes a connection break every time a video end, and the stream is ready to go when the next video begins.
I would like to stream those videos without any connection breaks continuously, then the stream could be correctly viewed.
I use this command to stream my videos one by one to the server
ffmpeg -re -y -i myvideo.mp4 -vcodec libx264 -b:v 600k -r 25 -s 640x360 \
-filter:v yadif -ab 64k -ac 1 -ar 44100 -f flv \
"rtmp://mystreamingserver/app/streamName"
I looked for some workarounds over the internet for many days, and i found some people talking about using a named pipe as input in ffmpeg, I've tried it and it didn't work well since ffmpeg does not only close the RTMP stream when a new video comes but also closes itself.
Is there any way to do this ? (stream a dynamic playlist of videos with ffmpeg to RTMP server without connection breaks
Update (as I can't delete the accepted answer): the proper solution is to implement a custom demuxer, similar to the concat one. There's currently no other clean way. You have to get your hands dirty and code!
Below is an ugly hack. This is a very bad way to do it, just don't!
The solution uses the concat demuxer and assumes all your source media files use the same codec. The example is based on MPEG-TS but the same can be done for RTMP.
Make a playlist file holding a huge list of entry points for you dynamic playlist with the following format:
file 'item_1.ts'
file 'item_2.ts'
file 'item_3.ts'
[...]
file 'item_[ENOUGH_FOR_A_LIFETIME].ts'
These files are just placeholders.
Make a script that keeps track of you current playlist index and creates symbolic links on-the-fly for current_index + 1
ln -s /path/to/what/to/play/next.ts item_1.ts
ln -s /path/to/what/to/play/next.ts item_2.ts
ln -s /path/to/what/to/play/next.ts item_3.ts
[...]
Start playing
ffmpeg -f concat -i playlist.txt -c copy output -f mpegts udp://<ip>:<port>
Get chased and called names by an angry system administrator
Need to create two playlist files and at the end of each file specify a link to another file.
list_1.txt
ffconcat version 1.0
file 'item_1.mp4'
file 'list_2.txt'
list_2.txt
ffconcat version 1.0
file 'item_2.mp4'
file 'list_1.txt'
Now all you need is to dynamically change the contents of the next playlist file.
You can pipe your loop to a buffer, and from this buffer you pipe to your streaming instance.
In shell it would look like:
#!/bin/bash
for i in *.mp4; do
ffmpeg -hide_banner -nostats -i "$i" -c:v mpeg2video \
[proper settings] -f mpegts -
done | mbuffer -q -c -m 20000k | ffmpeg -hide_banner \
-nostats -re -fflags +igndts \
-thread_queue_size 512 -i pipe:0 -fflags +genpts \
[proper codec setting] -f flv rtmp://127.0.0.1/live/stream
Of course you can use any kind of loop, also looping through a playlist.
I figure out that mpeg is a bit more stabile, then x264 for the input stream.
I don't know why, but minimum 2 threads for the mpeg compression works better.
the input compression need to be faster then the output frame rate, so we get fast enough new input.
Because of the non-continuing timestamp we have to skip them and generate a new one in the output.
The buffer size needs to be big enough for the loop to have enough time to get the new clip.
Here is a Rust based solution, which uses this technique: ffplayout
This uses a JSON playlist format. The Playlist is dynamic, in that way that you can edit always the current playlist and change tracks or add new ones.
Very Late Answer, but I recently ran into the exact same issue as the poster above.
I solved this problem by using OBS and the OBS websockets plugin.
First, set your RTMP streaming app as you have it now. but stream to a LOCAL RTMP stream.
Then have OBS load this RTMP stream as a VLC source layer with the local RTMP as the source.
then (in your app), using the OBS websockets plugin, have your VLC source switch to a static black video or PNG file when the video ends. Then switch back to the RTMP stream once the next video starts. This will prevent the RTMP stream from stopping when the video ends. OBS will go black durring the short transition, but the final OBS RTMP output will never stop.
There is surely a way to do this with manually setting up a intermediate RTMP server that pushes to a final RTMP server, but I find using OBS to be easier, with little overhead.
I hope this helps others, this solutions has been working incredible for me.