Newest 'ffmpeg' Questions - Stack Overflow
Les articles publiés sur le site
-
Merge video with ffmpeg
29 mai, par BjörnI have tried this command:
ffmpeg -i 'concat:10.mov|11.mov' -codec copy out.mov
The output file out.mov only shows whats in the first movie (10.mov).Been googling for several hours and tried lots of things but nothing works. I want this done without re-encoding the files. Just merge with the same codec
ffmpeg version 3.2.4 Copyright (c) 2000-2017 the FFmpeg developers built with Apple LLVM version 8.0.0 (clang-800.0.42.1) configuration: --prefix=/usr/local/Cellar/ffmpeg/3.2.4 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-libmp3lame --enable-libx264 --enable-libxvid --enable-opencl --disable-lzma --enable-vda libavutil 55. 34.101 / 55. 34.101 libavcodec 57. 64.101 / 57. 64.101 libavformat 57. 56.101 / 57. 56.101 libavdevice 57. 1.100 / 57. 1.100 libavfilter 6. 65.100 / 6. 65.100 libavresample 3. 1. 0 / 3. 1. 0 libswscale 4. 2.100 / 4. 2.100 libswresample 2. 3.100 / 2. 3.100 libpostproc 54. 1.100 / 54. 1.100 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7ff678802600] Found duplicated MOOV Atom. Skipped it Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'concat:10.mov|11.mov': Metadata: creation_time : 2017-03-17T12:15:22.000000Z major_brand : qt minor_version : 537134592 compatible_brands: qt Duration: 00:00:29.96, start: 0.000000, bitrate: 140810 kb/s Stream #0:0: Video: prores (apcn / 0x6E637061), yuv422p10le, 1280x720, 116735 kb/s, SAR 1:1 DAR 16:9, 50 fps, 50 tbr, 5k tbn, 5k tbc (default) Metadata: handler_name : Telestream Inc. Telestream Media Framework - Local 99.99.999999 encoder : Apple ProRes 422 Output #0, mov, to 'out.mov': Metadata: compatible_brands: qt major_brand : qt minor_version : 537134592 encoder : Lavf57.56.101 Stream #0:0: Video: prores (apcn / 0x6E637061), yuv422p10le, 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 116735 kb/s, 50 fps, 50 tbr, 10k tbn, 5k tbc (default) Metadata: handler_name : Telestream Inc. Telestream Media Framework - Local 99.99.999999 encoder : Apple ProRes 422 Stream mapping: Stream #0:0 -> #0:0 (copy) Press [q] to stop, [?] for help frame= 1498 fps=0.0 q=-1.0 Lsize= 426938kB time=00:00:29.94 bitrate=116815.8kbits/s speed=50.8x video:426930kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.001997%
Any ideas? Would make my life very much easier if I got this to work :)
-
Reuse PlainTransport for new FFmpeg stream without full reinit [closed]
29 mai, par Sang VoI'm building a backend-driven streaming application using Mediasoup + FFmpeg + PlainTransport.
My goal is to switch between different media sources (e.g.
welcome.mp4
,waiting.mp4
,streaming.ts
) from backend, while keeping the samePlainTransport
alive to avoid the overhead of tearing down and rebuilding the pipeline.Current setup
Backend: NestJS server with Mediasoup
Media ingest: FFmpeg sends RTP stream to PlainTransport
Producer: created after FFmpeg starts
Frontend: React client that consumes via Consumer after signaling
What I want
When the backend starts streaming a file (e.g., welcome.mp4), I want to:
- Start FFmpeg again with welcome.mp4 using the same RTP ports (same PlainTransport)
- After welcome is
wailting.mp4
. When has event streaming start play streaming, end event streaming play wailting - Create a new Producer with the new stream
- Notify the frontend to create a new Consumer
All this without having to destroy and recreate the
PlainTransport
for all eventQuestions
Is this a valid and recommended workflow in Mediasoup?
If so, does Mediasoup allow reusing the same PlainTransport across multiple Producer instances (one at a time)?
Will RTP stream re-sync correctly if FFmpeg restarts and sends new RTP packets?
Is it necessary to explicitly configure SSRC and payloadType to match, or will Mediasoup auto-detect again per new producer?
Any insights or recommendations on best practices for this dynamic switching scenario would be very helpful!
Thanks in advance 🙏
-
🧵 [QUESTION][QUESTION] Reuse PlainTransport for new FFmpeg stream without full reinit
29 mai, par Sang VoI'm building a backend-driven streaming application using Mediasoup + FFmpeg + PlainTransport. My goal is to switch between different media sources (e.g. welcome.mp4, waiting.mp4, streaming.ts) from backend, while keeping the same PlainTransport alive to avoid the overhead of tearing down and rebuilding the pipeline.
✅ Current Setup: Backend: NestJS server with Mediasoup
Media ingest: FFmpeg sends RTP stream to PlainTransport
Producer: created after FFmpeg starts
Frontend: React client that consumes via Consumer after signaling
🔄 What I want: When the backend Start streaming a file (e.g., welcome.mp4), I want to:
Start FFmpeg again with welcome.mp4 using the same RTP ports (same PlainTransport) After welcome is wailting.mp4. When has event streaming start play streaming, end event streaming play wailting
Create a new Producer with the new stream
Notify the frontend to create a new Consumer
All this without having to destroy and recreate the PlainTransport for all event
🧠 Questions: Is this a valid and recommended workflow in Mediasoup?
If so, does Mediasoup allow reusing the same PlainTransport across multiple Producer instances (one at a time)?
Will RTP stream re-sync correctly if FFmpeg restarts and sends new RTP packets?
Is it necessary to explicitly configure SSRC and payloadType to match, or will Mediasoup auto-detect again per new producer?
Any insights or recommendations on best practices for this dynamic switching scenario would be very helpful!
Thanks in advance 🙏
-
How to capture a web stream's picture in swift without playing it
28 mai, par SergioI am developing an application for iOS in which I need to capture one frame from the stream at every minute to show in a picture view.
I am thinking to use ffmpeg. I tried the
ffmpeg
command in my Mac terminal and it works:ffmpeg -probesize 4096 -analyzeduration 50000 -threads 1 -i -vf fps=fps=1 -frames 1 -threads 1 -y -s 320×240 -f mjpeg -pix_fmt yuvj444p
.jpg But I don't know how to call my compiled ffmpeg for iOS inside my app (I already have compiled it, with the '.a' libs).
I also read about using something like (not ffmpeg):
func thumbnail(sourceURL sourceURL:NSURL) -> UIImage? { let asset = AVAsset(URL: sourceURL) let imageGenerator = AVAssetImageGenerator(asset: asset) imageGenerator.appliesPreferredTrackTransform = true var time = asset.duration time.value = min(time.value, 2) do { let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil) return UIImage(CGImage: imageRef) } catch let error as NSError { print("Image generation failed with error \(error)") return nil; } }
but it doesn't work. It returns this error:
Image generation failed with error Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x15734af0 {Error Domain=NSOSStatusErrorDomain Code=-12782 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12782)}
fatal error: unexpectedly found nil while unwrapping an Optional value -
Safari sends excessive HTTP range requests during HTML5 MOV playback
28 mai, par LucyI am currently developing a web application based on React and Next.js, and I use the react-player library to play user-uploaded videos stored on AWS S3. The supported upload video formats are mp4, mov, and mkv, with codecs including H.264 or H.265 (HEVC).
Problem
However, some
H.264
videos in themov
format exhibit noticeably poor playback performance only in the Safari browser. The videos do not play smoothly and frequently experience stuttering or delays.How Safari Handles Range Requests (As I Understand It):
- Safari first sends a normal GET request to check if the server supports Range requests. If the server responds with the header Accept-Ranges: bytes, Safari closes the connection.
- Then, Safari sends a very small range request like Range: bytes=0-1 to confirm it receives a 206 Partial Content response.
- Next, Safari requests some parts from the beginning and the end of the file to locate metadata such as the moov atom in MP4 files.
- After that, actual streaming begins, but Safari does not request the entire file at once; instead, it divides the needed parts into multiple small Range requests.
Example of Actual Problematic Requests
Below are some of the Range requests Safari makes for the problematic
.mov
video (H.264 codec):# Request - 1 Connection: keep-alive Range: bytes=0-1 # Response HTTP/1.1 206 Partial Content Accept-Ranges: bytes Content-Disposition: attachment;filename*=utf-8''test.mov Content-Length: 2 Content-Range: bytes 0-1/102801747 Content-Type: video/quicktime ------------------------------------- # Request - 2 Connection: Keep-Alive Range: bytes=0-102801746 # Response HTTP/1.1 206 Partial Content Accept-Ranges: bytes Content-Disposition: attachment;filename*=utf-8''test.mov Content-Length: 102801747 Content-Range: bytes 0-102801746/102801747 Content-Type: video/quicktime ------------------------------------- # Request - 3 Connection: Keep-Alive Range: bytes=102760448-102801746 # Response - 3 HTTP/1.1 206 Partial Content Accept-Ranges: bytes Content-Disposition: attachment;filename*=utf-8''test.mov Content-Length: 41299 Content-Range: bytes 102760448-102801746/102801747 Content-Type: video/quicktime ------------------------------------- # Request - 4 Connection: keep-alive Range: bytes=3014656-3080191 # 64KB # Response - 4 HTTP/1.1 206 Partial Content Accept-Ranges: bytes Content-Disposition: attachment;filename*=utf-8''IMG_7929.mov Content-Length: 65536 Content-Range: bytes 3014656-3080191/102801747 Content-Type: video/quicktime
Safari continues to send hundreds of similar small Range requests repeatedly, gradually downloading the file.
This causes increased network load, which ultimately leads to video stuttering or playback delays.
Example of another
.mov
file that works properly:In contrast, another .mov video using the same format and codec (H.264) sends Range requests over much larger byte ranges, downloading about 30MB of data at once. In this case, the video plays smoothly.
# Request Connection: Keep-Alive Range: bytes=1310534-673918954 # Request : 672MB, Actual Downloaded : 32MB # Response Accept-Ranges: bytes Content-Disposition: attachment;filename*=utf-8''mov-example-video-download-4k-uhd-3840x2160.mov Content-Length: 672608421 Content-Range: bytes 1310534-673918954/673918955 Content-Type: video/quicktime
Question
In Safari, for certain video files, the browser repeatedly closes the connection after receiving only a few kilobytes per request and immediately sends the next request. As a result, dozens or even hundreds of small range requests occur consecutively. This causes increased connection overhead and latency, and although the web server can deliver data at sufficient speed, the player does not receive data in time, leading to poor and stuttering video playback.
- What could be the reason Safari repeatedly makes these very small requests for certain files?
- Could the internal structure of the video file (such as the moov atom) influence this request pattern?
f you have any similar experience or advice, please share.
What I'ved tried
- Using
ffmpeg
to move themoov atom
to the beginning of the file with-movflags faststart
does not resolve the issue — the same problem persists. - Converting the exact same video to MP4 format and testing it results in normal playback without issues.
Test Environment
- Macbook pro 16
- mac OS - Sequoia 15.5
- Safari - Latest
File information
Due to company policy, I am unable to share the problematic video files directly. However, I am attaching the file information obtained via ffprobe for your reference.
ffprobe -v error -show_format -show_streams -print_format json test.mov { "streams": [ { "index": 0, "codec_name": "h264", "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10", "profile": "High", "codec_type": "video", "codec_tag_string": "avc1", "codec_tag": "0x31637661", "width": 3840, "height": 2160, "coded_width": 3840, "coded_height": 2160, "closed_captions": 0, "film_grain": 0, "has_b_frames": 0, "pix_fmt": "yuv420p", "level": 51, "color_range": "tv", "color_space": "bt709", "color_transfer": "bt709", "color_primaries": "bt709", "chroma_location": "left", "field_order": "progressive", "refs": 1, "is_avc": "true", "nal_length_size": "4", "id": "0x1", "r_frame_rate": "30000/1001", "avg_frame_rate": "18200/607", "time_base": "1/600", "start_pts": 0, "start_time": "0.000000", "duration_ts": 10925, "duration": "18.208333", "bit_rate": "44900923", "bits_per_raw_sample": "8", "nb_frames": "546", "extradata_size": 158, "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0, "non_diegetic": 0, "captions": 0, "descriptions": 0, "metadata": 0, "dependent": 0, "still_image": 0, "multilayer": 0 }, "tags": { "creation_time": "", "language": "und", "handler_name": "Core Media Video", "vendor_id": "[0][0][0][0]", "encoder": "H.264" } }, { "index": 1, "codec_name": "aac", "codec_long_name": "AAC (Advanced Audio Coding)", "profile": "LC", "codec_type": "audio", "codec_tag_string": "mp4a", "codec_tag": "0x6134706d", "sample_fmt": "fltp", "sample_rate": "44100", "channels": 2, "channel_layout": "stereo", "bits_per_sample": 0, "initial_padding": 0, "id": "0x2", "r_frame_rate": "0/0", "avg_frame_rate": "0/0", "time_base": "1/44100", "start_pts": 0, "start_time": "0.000000", "duration_ts": 802988, "duration": "18.208345", "bit_rate": "187218", "nb_frames": "787", "extradata_size": 2, "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0, "non_diegetic": 0, "captions": 0, "descriptions": 0, "metadata": 0, "dependent": 0, "still_image": 0, "multilayer": 0 }, "tags": { "creation_time": "", "language": "und", "handler_name": "Core Media Audio", "vendor_id": "[0][0][0][0]" } }, { "index": 2, "codec_type": "data", "codec_tag_string": "mebx", "codec_tag": "0x7862656d", "id": "0x3", "r_frame_rate": "0/0", "avg_frame_rate": "0/0", "time_base": "1/600", "start_pts": 0, "start_time": "0.000000", "duration_ts": 10925, "duration": "18.208333", "bit_rate": "4", "nb_frames": "1", "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0, "non_diegetic": 0, "captions": 0, "descriptions": 0, "metadata": 0, "dependent": 0, "still_image": 0, "multilayer": 0 }, "tags": { "creation_time": "", "language": "und", "handler_name": "Core Media Metadata" } }, { "index": 3, "codec_type": "data", "codec_tag_string": "mebx", "codec_tag": "0x7862656d", "id": "0x4", "r_frame_rate": "0/0", "avg_frame_rate": "0/0", "time_base": "1/600", "start_pts": 0, "start_time": "0.000000", "duration_ts": 10925, "duration": "18.208333", "bit_rate": "6756", "nb_frames": "80", "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0, "non_diegetic": 0, "captions": 0, "descriptions": 0, "metadata": 0, "dependent": 0, "still_image": 0, "multilayer": 0 }, "tags": { "creation_time": "", "language": "und", "handler_name": "Core Media Metadata" } }, { "index": 4, "codec_type": "data", "codec_tag_string": "mebx", "codec_tag": "0x7862656d", "id": "0x5", "r_frame_rate": "0/0", "avg_frame_rate": "0/0", "time_base": "1/600", "start_pts": 0, "start_time": "0.000000", "duration_ts": 10925, "duration": "18.208333", "bit_rate": "50764", "nb_frames": "546", "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0, "non_diegetic": 0, "captions": 0, "descriptions": 0, "metadata": 0, "dependent": 0, "still_image": 0, "multilayer": 0 }, "tags": { "creation_time": "", "language": "und", "handler_name": "Core Media Metadata" } }, { "index": 5, "codec_type": "data", "codec_tag_string": "mebx", "codec_tag": "0x7862656d", "id": "0x6", "r_frame_rate": "0/0", "avg_frame_rate": "0/0", "time_base": "1/600", "start_pts": 0, "start_time": "0.000000", "duration_ts": 10925, "duration": "18.208333", "bit_rate": "19", "nb_frames": "1", "disposition": { "default": 1, "dub": 0, "original": 0, "comment": 0, "lyrics": 0, "karaoke": 0, "forced": 0, "hearing_impaired": 0, "visual_impaired": 0, "clean_effects": 0, "attached_pic": 0, "timed_thumbnails": 0, "non_diegetic": 0, "captions": 0, "descriptions": 0, "metadata": 0, "dependent": 0, "still_image": 0, "multilayer": 0 }, "tags": { "creation_time": "", "language": "und", "handler_name": "Core Media Metadata" } } ], "format": { "filename": "test.mov", "nb_streams": 6, "nb_programs": 0, "nb_stream_groups": 0, "format_name": "mov,mp4,m4a,3gp,3g2,mj2", "format_long_name": "QuickTime / MOV", "start_time": "0.000000", "duration": "18.208345", "size": "102801747", "bit_rate": "45166871", "probe_score": 100, "tags": { "major_brand": "qt ", "minor_version": "0", "compatible_brands": "qt ", "creation_time": "", "com.apple.quicktime.location.accuracy.horizontal": "76.200233", "com.apple.quicktime.full-frame-rate-playback-intent": "0", "com.apple.quicktime.location.ISO6709": "", "com.apple.quicktime.make": "Apple", "com.apple.quicktime.model": "iPhone 15 Pro", "com.apple.quicktime.software": "18.4.1", "com.apple.quicktime.creationdate": "" } } }