Opened 7 years ago
Last modified 6 years ago
#7281 new defect
fMP4 Single File Generation is excruciatingly slow
Reported by: | Ronak Patel | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | avformat |
Version: | git-master | Keywords: | hls |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
Summary of the bug:
Using a 20 hour audio mp4 file, try to make an fMP4 file (either HLS or DASH/HLS mode), using -codec copy to ensure there's no encoding being done. ffmpeg will take several hours to fragment the file.
Compare this to Apple's HLS Tools: https://developer.apple.com/streaming/ which is able to fragment in roughly 1 minute.
How to reproduce:
% ffmpeg -i "$FILE.mp4" -codec copy -hls_time 0.975238095238095 -hls_segment_type fmp4 -hls_flags single_file+append_list+split_by_time -hls_playlist_type vod "$FILE.m3u8" ffmpeg version ffmpeg version git-2018-06-23-b86c575 Copyright (c) 2000-2018 the FFmpeg developers built with Apple LLVM version 9.1.0 (clang-902.0.39.2) configuration: --prefix=/usr/local/Cellar/ffmpeg/HEAD-b86c575 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-gpl --enable-libfdk-aac --enable-libmp3lame --enable-libopus --enable-librubberband --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma --enable-nonfree libavutil 56. 18.102 / 56. 18.102 libavcodec 58. 20.103 / 58. 20.103 libavformat 58. 17.101 / 58. 17.101 libavdevice 58. 4.101 / 58. 4.101 libavfilter 7. 25.100 / 7. 25.100 libavresample 4. 0. 0 / 4. 0. 0 libswscale 5. 2.100 / 5. 2.100 libswresample 3. 2.100 / 3. 2.100 libpostproc 55. 2.100 / 55. 2.100 Hyper fast Audio and Video encoder usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
Change History (11)
comment:1 by , 7 years ago
Keywords: | fMP4 removed |
---|---|
Priority: | important → normal |
comment:2 by , 6 years ago
I analyzed the issue, but I'm filing this ticket so I can get help from the community to fix this issue. The fix for this issue looks involved with many use cases to test for once we fix the problem.
Just to summarize, I'm including the research I've done on this issue so far:
Hey Carl,
So I dug into this more today and I have root caused what's exactly happening here.
The problematic code is this: https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/hlsenc.c#L1368
This is where the filename is set and the next line actually opens the file.
The logic for this hls_window method is the following:
- Make a new temporary file.
- Write out a new HLS manifest header.
- Loop through all available segments and write out all of the entries for them.
- Close the temporary file when finished.
- Rename the temporary file to the target file name.
- Rinse and repeat for every single fragment.
Therefore, if you can imagine a 153 hour audio file, we write out a totally new HLS manifest 550800 times (153 * 60 * 60 assuming a 1s fragment duration) that gets progressively larger as each fragment is generated.
This is a classic O(N2) algorithm implementation, instead of:
- Creating the destination file up front & write the manifest header.
- Append the new segment to the file.
- If this is the last segment, write out EXT-X-ENDLIST.
There's no looping involved, nor the need to make temporary files.
FYI that I've noticed the same sort of pattern being applied to MPEG DASH: https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/dashenc.c#L786
To implement something like this, looks like we'd have to significantly re-engineer the code. Do you have any pointers on how to go about doing this? Or, would you be able to help do this?
Thanks for all your help,
Ronak
comment:3 by , 6 years ago
I've made the changes I've suggested and they work fine for the VOD and EVENT use cases. I haven't been able to test my changes with encryption, or true live HTTP Streams. Is there an easy way to set up for this test?
comment:4 by , 6 years ago
Have you already sent your patch - made with git format-patch
- as an attachment to the development mailing list for review?
follow-up: 6 comment:5 by , 6 years ago
Not yet, I'd like to make sure that my fix is actually working in every use case, before I put it up for review. Also, I've noticed that the segmentation is not consistent through the file when I choose mpegts containers. I would like to have this fixed, since it means my fix won't work perfectly with mpegts based streams.
Do you know what file I should look at where I can fix this?
comment:6 by , 6 years ago
Replying to ronak2121:
Not yet, I'd like to make sure that my fix is actually working in every use case, before I put it up for review.
This is often a (very) bad strategy.
comment:7 by , 6 years ago
I've just sent my first patch to ffmpeg for this issue. I'll send a second patch to fix issues in dashenc.c.
comment:8 by , 6 years ago
Was this fixed today?
Please remember to mention the ticket in the commit message.
comment:9 by , 6 years ago
I'm going to submit another patch that fixes this same problem for dashenc.c. I should have the patch up today or tomorrow at the latest.
comment:10 by , 6 years ago
The rename part in the current behavior is essential because it makes manifest updates atomic. This is important for live streams.
comment:11 by , 6 years ago
Then you should only do it for live streams. You are adding unnecessary overhead for VOD streams that don’t care about this.
This is currently at least missing the command line you tested together with the complete, uncut console output but I believe using
time
will make this ticket easier to understand.Didn’t you already analyse the issue?