Newest 'ffmpeg' Questions - Stack Overflow

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

Les articles publiés sur le site

  • Random audio/video sync issue with libcamera-vid + ffmpeg on raspberry pi 3a+

    8 mai, par kepperi

    I have been working on camera software, which will stream live fullhd video to Cloudflare Stream via RTMPS protocol. Everything is mostly working nicely, but I have occasional A/V sync issues with the streams: Stream might start with correct A/V sync and it will stay correct until the end (1-2 h stream), but sometimes the A/V sync is misaligned like 1-2 sec so, that the audio is either behind or ahead of the video stream. And it will be like that until the end of the stream, then next stream might be just fine.

    I'm using libcamera-vid for the video and ffmpeg for the audio, muxing and sending all to Cloudflare. This is my command:

    libcamera-vid 
      --width 1920 --height 1080 --framerate 30 --timeout 0 
      --nopreview true --inline 1 --codec h264 --verbose 0 
      --intra 90 --bitrate 4000000 --output - | 
    ffmpeg 
      -use_wallclock_as_timestamps 1 -loglevel error 
      -probesize 10M -analyzeduration 5M 
      -fflags +genpts -thread_queue_size 512 -f h264 -framerate 30 -i - 
      -thread_queue_size 8192 -itsoffset 0.7 
      -f alsa -channels 1 -ar 44100 -i hw:1,0 
      -c:v copy -c:a aac -b:a 96000 -fflags +genpts -async 1 -shortest -f flv - | 
    ( sleep 5; ffmpeg -re -i - -c copy -f flv "rtmps://live.cloudflare.com:443/live/..."
    

    So I can control initial A/V sync with -itsoffset and it is working, but still I encounter those random sync differences.

    I have also added the second ffmpeg command with 5 sec sleep to give the first ffmpeg process enough time to align with video and audio input before sending them to Cloudflare, but this seems not helping.

    I have also tried with Gstreamer, which fixed the AV issue completely, but it had weird glitches on video frames if the audio was enabled. Seemed like it tried to match the audio and video timestamps on fly and that caused warps/jumps and ghost frames on video. Audio was just fine.

    Here is my Gstreamer command (which will also have the same libcamera-vid piped in via fdsrc)

    GST_CLOCK_SYSTEM=1 gst-launch-1.0 -v
       fdsrc blocksize=524288 !
       h264parse config-interval=1 disable-passthrough=true !
       queue max-size-buffers=200 max-size-time=4000000000 max-size-bytes=0 !
       flvmux name=mux streamable=true latency=200 !
       queue max-size-buffers=200 max-size-time=4000000000 max-size-bytes=0 !
       rtmpsink sync=false location="rtmps://live.cloudflare.com:443/live/..."
       alsasrc device=hw:1,0 buffer-time=1000000 latency-time=200000 !
       audio/x-raw,rate=44100,channels=1,format=S16LE !
       queue leaky=downstream max-size-buffers=500 max-size-time=15000000000 max-size-bytes=0 !
       audioconvert ! audioresample ! avenc_aac bitrate=96000 ! aacparse !
       queue max-size-buffers=100 max-size-time=4000000000 max-size-bytes=0 ! mux.
    

    With Gstreamer, I have been experimenting different sizes of buffers, but no luck getting rid of the video glitches. If I remove audio from that gst-launch-1.0 command, video is just perfect.

    Hardware:

    I have also tried MUX instead of Cloudflare Stream, both acts identically so I guess the problem is not in receiving end encoding. This is also the reason I have not yet tried to "stream" into file.

    Currently I'm in a process of testing the libcamera-vid with raw yuv420 + ffmpeg but with ffmpeg encoding the video instead of just having encoded h264 from libcamera-vid. This is done with RPI4 since it has enough CPU for it.

    All help is appreciated!

  • ffmpeg, stretch audio to x seconds

    8 mai, par Max Doumit

    I am trying to make an audio file be exactly x second.

    So far i tried using the atempo filter by doing the following calculation

    Audio length / desired length = atempo.

    But this is not accurate, and I am having to tweak the tempo manually to get it to an exact fit.

    Are there any other solutions to get this work ? Or am I doing this incorrectly?

    My original file is a wav file, and my output in an mp3

    Here is a sample command

    ffmpeg -i input.wav -codec:a libmp3lame -filter:a "atempo=0.9992323" -b:a 320K output.mp3
    

    UPDATE:

    I was able to correctly calculate the tempo by changing the way I am receiving the audio length.

    I am now calculating the current audio length using the actual file size and the sample rate.

    Audio Length = file size / (sample rate * 2)
    

    Sample rate is something like 16000 Hz. You can get that by using ffprob or ffmpeg.

  • Major quality loss when encoding with ffmpeg [closed]

    6 mai, par Player_X_YT

    I am trying to edit videos in davinci resolve. It has limitations on what encoding I can import in the free version. I am trying to get around this by re-encoding the video file with ffmpeg. The following command is used to isolate the video track and encode it with mpeg-4:

    ffmpeg -y -i "$1" -an -vcodec mpeg4 "$1-VIDEO.mp4"
    

    However there is a significant loss in quality. I tried to force lossless quality but it doesn't change anything:

    ffmpeg -y -i "$1" -an -crf 0 -vcodec mpeg4 "$1-VIDEO.mp4"
    

    The video when rendered looks like it would when the bitrate drops, as in the pixels show up during motion. But dolphin states that the bitrate is actually higher than the source 2.6M -> 3.01M why do the videos continue to look like this?

  • cmake installation of x265 for ffmpeg on Cygwin - executable location different from other codecs

    6 mai, par bballdave025

    TL;DR (with expected vs. real)

    For a Cygwin build of ffmpeg, I'm installing x265, and it seems to me that the executable ends up in the wrong place. I'll show some basic directory structure, then I'll show the tree outputs for expected and real, both before and after the cmake installation. For directories where I think this is important, I'll show the outputs before and after the cmake installation.

    My question has two parts. I used the following cmake and make commands,

    # pwd => $HOME/programs/ffmpeg/ffmpeg_sources/x265/build/linux
    PATH="$HOME/programs/ffmpeg/bin:$PATH" \
      cmake -G "Unix Makefiles" \
            -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \
            -DENABLE_SHARED=OFF \
            -DCMAKE_EXE_LINKER_FLAGS="-static" 
                ../../source
    PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc)
    make install
    

    The result is below, with my real vs. expected, and there is a more detailed, more explicit, and hopefully more clear file with the info. at pastebin.com/86wHrtxR.

    Edit: I've made a copy of the detailed/explicit/clear file on my GitHub as a gist. This should be more secure. (The Pastebin version still exists, in case that is your preference.)

    Now, for my two-part question:

    1. How can I change my cmake command so that my x265.exe file ends up in $HOME/programs/ffmpeg/bin with the proper linking, rather than $HOME/programs/ffmpeg/ffmpeg_build/bin?

    2. Would the build/linker/whatever figure things out for the ffmpeg build?

    I want to know the answer to question number 1 regardless of the answer to question number 2. I haven't used cmake with the -DVAR=var flags before, and I'd like to take this opportunity to learn.

    For the result:

    Things surrounded by double curly brackets are {{ expected }}.

    Things surrounded by double angle brackets are << real >>, i.e. they exist after the installation is done.

    If real matches expected, and the file/directory is new, I've surrounded it by double parentheses, i.e. double round brackets. (( match ))

    If something is not new (and thus has the same before and after) I haven't marked it.

       me@MACHINE ~/programs/ffmpeg
       $ tree --charset=ascii bin
       bin
       |-- lame.exe
       |-- mp3rtp.exe
       |-- mp3x.exe
       `-- x264.exe
    {{ `-- x265.exe                     }} ## Expected, not Exists
    
       me@MACHINE ~/programs/ffmpeg
       $ tree --charset=ascii \
                       ffmpeg_build
       ffmpeg_build
    << |-- bin                          >> ## Not expected, Exists
    << |   `-- x265.exe                 >> ## Not expected, Exists
       |-- include
       |   |-- fdk-aac
       |   |   |-- aacdecoder_lib.h
       |   |   |-- aacenc_lib.h
       |   |   `-- ... 
       |   |-- lame
       |   |   `-- lame.h
       |   |-- x264.h
       |   `-- x264_config.h
    (( |   |-- x265.h                   )) ## Expected and Exists
    (( |   `-- x265_config.h            )) ## Expected and Exists
       |-- lib
       |   |-- libfdk-aac.a
       |   |-- libfdk-aac.la
       |   |-- libmp3lame.a
       |   |-- libmp3lame.la
    (( |   |-- libx265.a                )) ## Expected and Exists
       |   `-- pkgconfig
       |       |-- fdk-aac.pc
       |       `-- x264.pc
    (( |       `-- x265.pc              )) ## Expected and Exists
       `-- share
           |-- doc
           |   ... 
           `-- man
               ... 
    

    Other, possibly useful information about the build directory structure.

    me@MACHINE ~/programs/ffmpeg
    $ tree --charset=ascii -L 1 .
    .
    |-- bin
    |-- ffmpeg_build
    `-- ffmpeg_sources
    
    3 directories, 0 files
    

    For this next, ffmpeg_sources dir, I'm showing the after (which is both expected and real/exists) surrounded by double parentheses, i.e. double round brackets, (( )).

       me@MACHINE ~/programs/ffmpeg
       $ tree --charset=ascii -L 1 ffmpeg_sources
       ffmpeg_sources
       |-- fdk-aac.zip
       |-- lame-svn
       |-- mstorsjo-fdk-aac-e7d8591
       |-- x264-snapshot-20191217-2245
       |-- x264-snapshot-20191217-2245.tar.bz2
       `-- x264-snapshot-20191218-README.txt
    (( `-- x265                         ))
    
       3 directories, 3 files
    (( 4 directories, 3 files ))
    

    NOW, FOR SOME MORE DETAIL


    What I'm Doing

    I am working on a Cygwin build (vs. a Windows/mingw build) of ffmpeg. I am following an older guide by koohiimaster (archived). That guide says,

    [W]e are not cross-compiling for windows; we are compiling for Cygwin.

    This 2014 guide doesn't have all of the codecs I want - I want as complete a build as possible - so I've also been referring to this ffmpeg-for-Ubuntu guide (archived), which I hope is kept up-to-date. It's referred to by koohiimaster.

    Also, as a way of checking that I'm getting all the codecs I want, I've been looking at this FFmpeg for Windows guide from SuperUser

    I'll give the basics of my steps below. More details, as well as all the output is at pastebin.com/suL1nU6Z.

    Edit: I've put the log of terminal input/output for all my steps into a gist at my GitHub as this seems safer than Pastebin.

    A look at directory structure for the build

    me@MACHINE ~/programs/ffmpeg
    $ cd $HOME/programs/ffmpeg
    
    me@MACHINE ~/programs/ffmpeg
    $ tree --charset=ascii -d -L 1
    .
    |-- bin
    |-- ffmpeg_build
    `-- ffmpeg_sources
    
    3 directories
    

    Getting the source. Note that I had to apt-cyg install mercurial, though (with my Cygwin setup GUI/EXE in my Cygwin root directory, i.e. C:\cygwin64\setup-x86_64.exe), I could also have done /setup-x86_64.exe install -q -P mercurial.

    cd ffmpeg_sources
    hg clone https://bitbucket.org/multicoreware/x265
    

    Running the cmake and make commands

    cd x265/build/linux
    PATH="$HOME/programs/ffmpeg/bin:$PATH" \
      cmake -G "Unix Makefiles" \
            -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \
            -DENABLE_SHARED=OFF \
            -DCMAKE_EXE_LINKER_FLAGS="-static" \
                ../../source
    PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc)
    make install
    

    It was the last part (actually the very last line) of the make install output that worried me. Here is the whole output - it's not very long.

    make[1]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    [ 20%] Built target encoder
    make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    [ 83%] Built target common
    make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    [ 84%] Built target x265-static
    make[2]: Entering directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    make[2]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    [100%] Built target cli
    make[1]: Leaving directory '/home/me/programs/ffmpeg/ffmpeg_sources/x265/build/linux'
    Install the project...
    -- Install configuration: "Release"
    -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/lib/libx265.a
    -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/include/x265.h
    -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/include/x265_config.h
    -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/lib/pkgconfig/x265.pc
    -- Installing: /home/me/programs/ffmpeg/ffmpeg_build/bin/x265.exe
    

    As discussed in the TL;DR section, I expected to see x265.exe at

    home/me/programs/ffmpeg/bin/x265.exe

    rather than the path given on the last line of output,

    /home/me/programs/ffmpeg/ffmpeg_build/bin/x265.exe

    This worries me especially because the first part of the ffmpeg install command that my instructions inform me to run is

    PATH="$HOME/programs/ffmpeg/bin:$PATH" \
    PKG_CONFIG_PATH="$HOME/programs/ffmpeg/ffmpeg_build/lib/pkgconfig" \
      ./configure \
        --prefix="$HOME/programs/ffmpeg/ffmpeg_build" \
        --extra-cflags="-I$HOME/programs/ffmpeg/ffmpeg_build/include" \
        --extra-ldflags="-L$HOME/programs/ffmpeg/ffmpeg_build/lib" \
        --bindir="$HOME/programs/ffmpeg/bin" \
    

    ... and on it goes ...

    It would seem to me that the .configure script for ffmpeg won't find the x265 executable, since it's not in the bindir.

    I'll repeat my two-part question from before:

    1. How can I change my cmake command so that my x265.exe file ends up in $HOME/programs/ffmpeg/bin with the proper linking, rather than $HOME/programs/ffmpeg/ffmpeg_build/bin?

    What I'm looking for here is something akin to the --bindir flag from make's ./confiure.

    1. Would the build/linker/whatever figure things out for the ffmpeg build?

    I want to know the answer to question number 1 regardless of the answer to question number 2. I haven't used cmake with the -DVAR=var flags before, and I'd like to take this opportunity to learn.


    Where I've Looked & What I've Tried

    I first started with the man page and the --help for cmake. That was scary. I was hoping that I'd find something useful around the CMAKE_INSTALL_PREFIX stuff, but I wasn't sure what to make of it.

    I tried greping through cmake --help-full (with 50 lines before and after whatever I was searching for), but got tripped up by the complexity. I've only used basic cmake stuff, before, and I got more than a little lost.

    Even with the --help, I don't know if I need to look at the help-manual, the help-command, the help-module, the help-policy, the help-variable, or something else.

    It seemed to me, in reading, that a "binary directory" is the top of the "build", whereas I thought it would be the dir named bin ... I couldn't tell what things were meant to be used by the person creating the package rather than by me, who am trying to make/build the package from the command line.

    I looked through what seemed to be a cmake wiki's Useful Variables page (archived), as well as at this thread at cmake.org (archived), which, along with this SO source and this and this and this and this SO sources, seemed to suggest using the CMAKE_RUNTIME_OUTPUT_DIRECTORY variable (since the EXECUTABLE_OUTPUT-DIRECTORY variable has been superseded by it). By the way, I couldn't tell which things should be used by the creator of the package vs. the consumer of the package - the consumer being me. I tried with

    PATH="$HOME/programs/ffmpeg/bin:$PATH" \
      cmake -G "Unix Makefiles" \
            -DCMAKE_INSTALL_PREFIX="$HOME/programs/ffmpeg/ffmpeg_build" \
            -DCMAKE_RUNTIME_OUTPUT_DIRECTORY="$HOME/programs/ffmpeg/bin" \
            -DENABLE_SHARED=OFF \
            -DCMAKE_EXE_LINKER_FLAGS="-static" 
                ../../source
    PATH="$HOME/
    

    and have thought about fifty-or-so other -DVAR variables, but with any I have tried, I still get the same result. I still get the executable in what seems to be the wrong place.


    System Details

    $ date && date +'%s'
    Tue, May  5, 2020 11:14:40 AM
    1588698880
    $ uname -a
    CYGWIN_NT-10.0 MACHINE 3.1.4(0.340/5/3) 2020-02-19 08:49 x86_64 Cygwin
    $ cmake --version
    cmake version 3.14.5
    
    CMake suite maintained and supported by Kitware (kitware.com/cmake).
    $ bash --version | head -n 1
    GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin)
    $ gcc --version | head -n 1
    gcc (GCC) 9.3.0
    $ g++ --version | head -n 1
    g++ (GCC) 9.3.0
    $ make --version | head -n 2
    GNU Make 4.3
    Built for x86_64-pc-cygwin
    
  • Button "Clean FFMeta" does nothing after compiling with PyInstaller

    6 mai, par Leonie Holdermann

    I’m working on my first Python project and I’ve compiled it into an executable using PyInstaller with the following command:

    pyinstaller --onefile --noconsole app.py
    

    However, when I run the executable, the button "Clean FFMeta" which triggers the clean_ffmeta() function does nothing. Additionally, changing the language or the chapter settings under the "Options -> Chapter settings" menu doesn’t seem to affect anything either. It all works perfectly in the Python script before compilation, but once compiled into an .exe, none of these functions respond.

    I've reviewed the code, and the button is correctly linked to the function, but I suspect something might be going wrong during the compilation process.

    What I have tried:

    • Checked that all dependencies are included.
    • Verified that the configuration and language changes are being correctly applied before compilation.
    • Tried running the executable from a console to check for error messages, but there are none visible (since I used --noconsole).

    What I expect:

    • The "Clean FFMeta" button should clean the FFMeta file based on the user settings.
    • Language and chapter settings should be updated and reflected in the GUI immediately.

    Code: Below is a simplified version of my code, especially the sections related to the "Clean FFMeta" functionality and language/chapter settings.

    def clean_ffmeta():
    if not config.get("cd_in_path"):
        show_error(texts[current_language]["error"] + " No CD_IN path configured.")
        return
    
    chapter_path = os.path.join(config["cd_in_path"], "chapters.ffmeta")
    cleaned_chapter_path = os.path.join(config["cd_in_path"], "chapters_cleaned.ffmeta")
    
    if not os.path.exists(chapter_path):
        show_error(texts[current_language]["no_chapters_file"])
        return
    
    write_to_console("Starting to clean FFMeta...")
    thread = threading.Thread(target=clean_ffmeta_thread, args=(chapter_path, cleaned_chapter_path))
    thread.start()
    
    def clean_ffmeta_thread(chapter_path, cleaned_chapter_path):
        try:
            chapter_action = config.get("chapter_action", "clean")
            keep_empty = config.get("chapter_keep_empty", False)
    
            write_to_console(f"Chapter action: {chapter_action}, Keep empty: {keep_empty}")
    
            with open(chapter_path, "r", encoding="utf-8") as f:
                lines = f.readlines()
    
            new_lines = []
            chapter_counter = 0
    
            for line in lines:
                stripped_line = line.strip()
                if stripped_line.startswith("title="):
                    title_content = stripped_line[6:]
                    
                    if chapter_action == "clean":
                        if title_content == "":
                            if keep_empty:
                                new_lines.append(line)
                            else:
                                write_to_console("Empty title skipped.")
                                continue
                        else:
                            new_lines.append(line)
                    
                    elif chapter_action == "number":
                        chapter_counter += 1
                        chapter_title = f"{texts[current_language]['chapter']} {chapter_counter}"
                        new_lines.append(f"title={chapter_title}\n")
                        write_to_console(f"Renamed to: {chapter_title}")
                else:
                    new_lines.append(line)
    
            with open(cleaned_chapter_path, "w", encoding="utf-8") as f:
                f.writelines(new_lines)
    
            write_to_console(f"FFMeta cleaned and saved as '{cleaned_chapter_path}'.")
    
        except Exception as e:
            write_to_console(f"Error cleaning FFMeta: {str(e)}")
    
    def open_chapter_settings():
        global chapter_settings_window, chapter_action_var
        global chapter_keep_empty_checkbox, chapter_save_button
    
        chapter_settings_window = tk.Toplevel(root)
        chapter_settings_window.title(texts[current_language]["chapter_setting_title"])
        chapter_settings_window.geometry("300x250")
        chapter_settings_window.resizable(False, False)
        
        chapter_action_var = tk.StringVar(value=config.get("chapter_action", "clean"))
        chapter_keep_empty_var = tk.BooleanVar(value=config.get("chapter_keep_empty", False))
        
        tk.Label(
            chapter_settings_window,
            text=texts[current_language]["chapter_setting_choose_option"]
        ).pack(pady=(10, 5))
        
        tk.Radiobutton(
            chapter_settings_window,
            text=texts[current_language]["chapter_setting_clean"],
            variable=chapter_action_var,
            value="clean"
        ).pack(pady=5)
    
        tk.Radiobutton(
            chapter_settings_window,
            text=texts[current_language]["chapter_setting_number"],
            variable=chapter_action_var,
            value="number"
        ).pack(pady=5)
    
        chapter_keep_empty_checkbox = tk.Checkbutton(
            chapter_settings_window,
            text=texts[current_language]["chapter_setting_keep_empty"],
            variable=chapter_keep_empty_var
        )
        chapter_keep_empty_checkbox.pack(pady=5)
    
        chapter_save_button = tk.Button(
            chapter_settings_window,
            text=texts[current_language]["chapter_setting_save"],
            command=lambda: save_chapter_settings(chapter_keep_empty_var, chapter_settings_window)
        )
        chapter_save_button.pack(pady=10)
    
    def save_chapter_settings(keep_empty_var, window):
        config["chapter_action"] = chapter_action_var.get()
        config["chapter_keep_empty"] = keep_empty_var.get()
        save_config()
        write_to_console(f"Chapter settings saved: Action={config['chapter_action']}, Keep empty={config['chapter_keep_empty']}")
        window.destroy()
    
    options_menu = tk.Menu(menu, tearoff=0)
    options_menu.add_command(label="Check pip-ffmpeg", command=check_pip_ffmpeg)
    options_menu.add_command(label=texts[current_language]["menu_chapter_settings"], command=open_chapter_settings)
    menu.add_cascade(label="Options", menu=options_menu)
    
    btn3 = tk.Button(btn_frame, text="3. Clean FFMeta", command=clean_ffmeta)
    btn3.grid(row=0, column=2, padx=5)
    

    Here you find the entire project code of the entire project: https://www.pythonmorsels.com/p/32hkh/

    Why is the clean_chapters function not working?