Newest 'ffmpeg' Questions - Stack Overflow

http://stackoverflow.com/questions/tagged/ffmpeg

Les articles publiés sur le site

  • How to capture a web stream's picture in swift without playing it

    28 mai, par Sergio

    I 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 Lucy

    I 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 the mov 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):

    1. 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.
    2. Then, Safari sends a very small range request like Range: bytes=0-1 to confirm it receives a 206 Partial Content response.
    3. 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.
    4. 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.

    1. What could be the reason Safari repeatedly makes these very small requests for certain files?
    2. 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 the moov 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": ""
            }
        }
    }
    
  • Real time HLS editing with FFmpeg filter_complex without re-encoding full stream

    28 mai, par Devdeep Ghosh

    I'm new to FFmpeg and working on a lightweight video editor for HLS streams that allows cutting and trimming without re-encoding the entire video. I'm using FFmpeg to only process the segments that intersect with "exclusion" ranges (timestamps to remove), while copying unmodified segments directly. The goal is speed and accuracy.

    The logic identifies which .ts segments overlap with exclusion windows, applies filter_complex to trim just those segments, and then programatically reassemble everything into a new .m3u8 playlist. However, the final output sometimes freezes or desynchronizes—audio gets out of sync or playback freezes where segments were excluded.

    Here's the FFmpeg logic I'm using to trim segments:

    const videoFilter = `[0:v]select='not(between(t,${start},${end}))'[vout]`;
    const audioFilter = `[0:a]aselect='not(between(t,${start},${end}))'[aout]`;
    
    
    const ffmpegArgs = [
      "-i", inputPath,
      "-filter_complex", `${videoFilter};${audioFilter};[vout]setpts='PTS-STARTPTS'[v];[aout]asetpts='PTS-STARTPTS'[a]`,
      "-map", "[v]",
      "-map", "[a]",
      "-c:v", "libx264",
      "-c:a", "aac",
      "-preset", "ultrafast",
      "-hls_flags", "independent_segments",
      "-avoid_negative_ts", "make_zero",
      "-y", outputPath,
    ];
    

    Is this approach actually viable for cutting .ts segments from an HLS stream without full re-encoding?

    Am I misunderstanding how FFmpeg handles timestamps when trimming?

    Is there a better or more reliable way to do this (e.g. concat, -ss/-to, GOP alignment, etc.)?

  • mp4 - Mooving moov atom in web js [closed]

    27 mai, par Ben Carp

    In a web app, recording is done with MeidaRecorder, which places the moov atom at the end. We want to generate a progressive video with moov at the start.

    Most of examples that I found use ffmpeg wasm which we can't use in our project. Is there an option to extract the video parts from the Blob/video chunks and to repack them in mp4 that will generate a new progressive mp4?

  • Python yt-dlp and ffmpeg error "merging of multiple formats but ffmpeg is not installed"

    27 mai, par T Tea Tie

    I am using the latest version of yt-dlp with Python 3.9.

    I am trying to download a youtube video in mp4 format with outputname as the youtubeid.mp4 and with best resolution not more than 4K.

    This is my Python code:

    ytid = '4cDqaLxrt6Q'
    url = 'https://www.youtube.com/watch?v='+ytid
    output_filename = ytid+".mp4"
        
    with YoutubeDL({'format': 'bestvideo[height<=?4K]+bestaudio/best', 'output': output_filename}) as ydl:
        ydl.download(url)`#TODO debug FFmpeg and check if outputname is ok
    

    I expected to have an .mp4 file in my current working directory.

    Then I installed the latest version of FFmpeg from ffmpeg-master-latest-win64-gpl.zip and put ffmpeg.exe, ffplay.exe and ffprobe.exe in Scripts python folder (where yt-dlp.exe is). I also installed ffmpeg using pip install.

    The Traceback is:

    [youtube] Extracting URL: https://www.youtube.com/watch?v=4cDqaLxrt6Q [youtube] 4cDqaLxrt6Q: Downloading webpage [youtube] 4cDqaLxrt6Q: Downloading android player API JSON [youtube] 4cDqaLxrt6Q: Downloading MPD manifest [youtube] 4cDqaLxrt6Q: Downloading MPD manifest [info] 4cDqaLxrt6Q: Downloading 1 format(s): 243+251 ERROR: You have requested merging of multiple formats but ffmpeg is not installed. Aborting due to --abort-on-error Traceback (most recent call last):

    File "C:\Users\t\OneDrive\Documents\Python Scripts\project\main.py", line 88, in ydl.download(url)

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 3353, in download self.__download_wrapper(self.extract_info)(

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 3328, in wrapper res = func(*args, **kwargs)

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 1486, in extract_info return self.__extract_info(url, self.get_info_extractor(key), download, extra_info, process)

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 1497, in wrapper return func(self, *args, **kwargs)

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 1594, in __extract_info return self.process_ie_result(ie_result, download, extra_info)

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 1653, in process_ie_result ie_result = self.process_video_result(ie_result, download=download)

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 2767, in process_video_result self.process_info(new_info)

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 3189, in process_info self.report_error(f'{msg}. Aborting due to --abort-on-error')

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 1007, in report_error self.trouble(f'{self._format_err("ERROR:", self.Styles.ERROR)} {message}', *args, **kwargs)

    File "C:\Users\t\anaconda3\lib\site-packages\yt_dlp\YoutubeDL.py", line 947, in trouble raise DownloadError(message, exc_info)

    DownloadError: ERROR: You have requested merging of multiple formats but ffmpeg is not installed. Aborting due to --abort-on-error