Newest 'ffmpeg' Questions - Stack Overflow

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

Les articles publiés sur le site

  • How to Capture a Sequence of High-Quality PDF Frames from a Website (Without Screen Recording) ?

    9 mars, par Pubg Mobile

    In Firefox, I can take very high-quality screenshots of a webpage by using Ctrl + P and saving the page as a PDF. This method preserves the text, images, and code in excellent resolution.

    Now, I have created a movable bar chart race in Flourish Studio and want to convert it into a high-quality video. However, I do not want to use screen recording tools.

    My Goal:
    I want to capture 30 high-resolution PDF frames from the website at different points in time (like a video sequence). Ideally, I need a tool or script that can automate the process of saving multiple PDFs from the website as it plays the animation.

    What I Tried:
    I attempted to write a Python script that:

    Opens the local HTML file of my Flourish chart in Firefox using Selenium.
    Waits for the page to load.
    Listens for the F1 key and triggers Ctrl + P to print the page as a PDF.
    However, the script does not save the PDF file in the output folder. I'm not sure why.

    Here is my code:

    import time
    import keyboard
    from selenium import webdriver
    from selenium.webdriver.firefox.service import Service
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.firefox.options import Options
    
    # Define paths
    html_file_path = r"E:\Desktop\New folder (4)\20250309101616805.html"
    geckodriver_path = r"E:\Desktop\New folder (4)\geckodriver.exe"
    save_path = r"E:\Desktop\New folder (4)\New folder\output.pdf"  # Save PDF location
    
    # Set up Firefox options
    options = Options()
    options.set_preference("print.always_print_silent", True)  # Silent printing
    options.set_preference("print.show_print_progress", False)  # Hide progress
    options.set_preference("print.print_to_file", True)  # Print to file
    options.set_preference("print.save_print_settings", True)  # Save settings
    options.set_preference("print.printer_PDF", "Save as PDF")  # Set printer
    options.set_preference("print.print_to_file", True)  # Enable saving print output to file
    options.set_preference("print.print_file_name", save_path)  # Define the save location for PDF
    
    # Start WebDriver
    service = Service(executable_path=geckodriver_path)
    driver = webdriver.Firefox(service=service, options=options)
    
    # Open the HTML file
    driver.get("file:///" + html_file_path)
    
    # Wait for the page to load
    time.sleep(2)
    
    print("Press F1 to save as PDF.")
    
    # Listen for F1 key press
    while True:
        if keyboard.is_pressed('F1'):
            print("F1 pressed, saving as PDF...")
            
            # Trigger print command (Ctrl + P)
            body = driver.find_element(By.TAG_NAME, 'body')
            body.send_keys(Keys.CONTROL + 'p')
            
            # Wait for the print dialog to process
            time.sleep(2)
    
            print("PDF should be saved to:", save_path)
            break
    
    # Close browser
    driver.quit()
    

    My Questions:

    Why is my script not saving the PDF in the specified output folder?

    Is there a better way to automate capturing 30 sequential PDFs from the website at different animation frames?

    Is there any tool or script that can generate a sequence of PDFs (like 30 frames per second) from a webpage?

    Important:

    I do NOT want to use screen recording tools.

    I only need high-quality PDF frames that can later be converted into a video.

    Any help would be greatly appreciated!

  • How can I dynamically update metadata in audio output with libav so that updates appear in MPV ?

    9 mars, par Teddy

    My ultimate goal is to proxy an internet radio station and programmatically add metadata to it during the stream that can be displayed and updated in MPV, the media player playing the audio.

    The metadata I would like to add is primarily the song title, but ideally additional information including artist, composer, and album.

    I envision running the proxy program like this:

    $ curl https://example.com/stream.mp3 | ./proxy_add_metadata | mpv -
    

    or maybe this:

    $ ./proxy_add_metadata &
    #=> 
    $ mpv 
    

    How could I make song metadata updates dynamically over time using libav?

    I’m using FFmpeg version 7.1.

    I first tried changing the metadata dictionary shortly before writing a frame with a few different container formats:

    av_dict_set(&output_ctx->metadata, "title", "Title 1", 0);
    /* [...] */
    av_interleaved_write_frame(output_ctx, packet);
    

    Setting metadata with av_dict_set(&output_ctx->metadata, "title", "Title 1", 0); only appears to work when done before writing the output header.

    My next idea was to try setting metadata in AVPacket side data, but I’m unclear which container formats support this for the kind of metadata I’m working with.

    I’m open to any output media container format or FFmpeg-originated network stream.

    It’s unclear to me whether the metadata should be written to a separate stream within the media container or whether it should be written as side data in the output packets.

    If what I’m trying to do is impossible, please explain why.

    What I have so far reads audio from standard input and writes it to standard output. The input audio can be assumed to be in MP3 format. Non-working sections for metadata updates are commented out.

    /* proxy_add_metadata.c */
    #include 
    
    #include avformat.h>
    #include avcodec.h>
    
    int main() {
        int _err;
    
        /* MP3 input */
        AVFormatContext *input_ctx = avformat_alloc_context();
        _err = avformat_open_input(&input_ctx, "pipe:0", NULL, NULL);
        _err = avformat_find_stream_info(input_ctx, NULL);
    
        AVFormatContext *output_ctx;
        _err = avformat_alloc_output_context2(&output_ctx, NULL, "matroska", "pipe:1");
    
        AVStream *input_stream = input_ctx->streams[0];
        AVStream *output_stream = avformat_new_stream(output_ctx, NULL);
    
        _err = avcodec_parameters_copy(output_stream->codecpar, input_stream->codecpar);
        _err = avio_open(&output_ctx->pb, "pipe:1", AVIO_FLAG_WRITE);
    
        _err = avformat_write_header(output_ctx, NULL);
    
        AVPacket *packet = av_packet_alloc();
    
        /* Set up packet side data. */
        /*
        AVDictionary *packet_side_data_dict;
        av_dict_set(&packet_side_data_dict, "title", "Title 1", 0);
    
        size_t packet_side_data_size = 0;
        uint8_t *packet_side_data = av_packet_pack_dictionary(
            packet_side_data_dict,
            &packet_side_data_size
        );
        av_dict_free(&packet_side_data_dict);
        */
    
        while (1) {
            _err = av_read_frame(input_ctx, packet);
            if (_err < 0) {
                break;
            }
    
            /* Can metadata updates be made here? */
    
            /* Option 1: Attempt to write metadata to the container. */
            /*
            _err = av_dict_set(&output_ctx->metadata, "title", "Title 1", 0);
            if (_err < 0) {
                fprintf(stderr, "error: can't set metadata title in stream: %s\n", av_err2str(_err));
                break;
            }
            */
    
            /* Option 2: Attempt to write metadata to packet side data. */
            /*
            _err = av_packet_add_side_data(
                packet,
                AV_PKT_DATA_METADATA_UPDATE,
                packet_side_data,
                packet_side_data_size
            );
            if (_err < 0) {
                fprintf(stderr, "error: can't add side data to packet: %s\n", av_err2str(_err));
                break;
            }
            */
    
            AVStream *input_stream = input_ctx->streams[packet->stream_index];
            AVStream *output_stream = output_ctx->streams[packet->stream_index];
    
            av_packet_rescale_ts(packet, input_stream->time_base, output_stream->time_base);
            packet->pos = -1;
    
            _err = av_interleaved_write_frame(output_ctx, packet);
            if (_err < 0) {
                fprintf(stderr, "error: packet write: %s\n", av_err2str(_err));
                break;
            }
        }
    
        av_write_trailer(output_ctx);
    
        av_packet_free_side_data(packet);
        av_packet_free(&packet);
    
        avio_closep(&output_ctx->pb);
        avformat_free_context(output_ctx);
    
        avformat_close_input(&input_ctx);
    
        return 0;
    }
    
    cc \
        -Wall \
        -g \
        -I/.../ffmpeg7/include \
        -o proxy_add_metadata \
        proxy_add_metadata.c \
        -L/.../ffmpeg7/lib -lavformat -lavcodec
    
    $ < sample.mp3 ./proxy_add_metadata | mpv -
    
  • Embedding "Dolby Digital Plus with Dolby Atmos" into MP4 using ffmpeg

    8 mars, par Krystian

    How can I encode Dolby Atmos into MP4? I am using this command ffmpeg -i input.mp4 -i input.ec3 -map 0:v -map 1:a -c:v copy -c:a copy -disposition:a default -metadata:s:a:0 complexity_index=16 -metadata:s:a:0 title="Dolby Atmos" output_test.mp4 I have to provide every single piece of data that is inside this EC3 file. I have noticed that when I am running this command the MP4 file contains actual Dolby Atmos stream but it's missing complexity index. Raw EC3 file has Complexity Index set to 16 but after adding it to MP4 file the complexity index is not present and this MP4 is not identified as a video with proper Dolby Atmos stream

    I thought that after using this command, complexity index will be added correctly. I don't want to use MKV but it looks like I will have to do that.

  • I use the bramp/ffmpeg-cli-wrapper of java. How to terminate the execution in the thread ?

    8 mars, par Hao Tan

    I want to use ffmpeg to achieve streaming function

    First I created a thread pool

     private final Map taskThreads = new ConcurrentHashMap<>();
    Thread taskThread = new Thread(() -> {
                try {
                    private void startTask(Device task) {
            Thread taskThread = new Thread(() -> {
    
                FFmpegBuilder builder = new FFmpegBuilder()
                        .setInput(source) 
                        .overrideOutputFiles(true)
                        .addOutput(destination) 
                        .setFormat("flv")
                        .addExtraArgs("-c", "copy") 
                        .done();
    
                FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
                executor.createJob(builder).run();
            });
            taskThreads.put(task.getId(), taskThread);
            taskThread.start();
        }
    

    stop code

    public void stopTask(Integer taskId) {
            Thread taskThread = taskThreads.get(taskId);
            if (taskThread != null) {
                taskThread.interrupt(); 
                taskThreads.remove(taskId);
                
                DeviceDto task = deviceService.findById(taskId);
                if (task != null) {
                    task.setIsOnline(0);
                    Device device = new Device();
                    BeanUtils.copyProperties(task,device);
                    deviceService.update(device);
                }
            }
        }
    

    I call stopTask and cannot terminate the ffmpeg thread

    It should be executor.createJob(builder).run(); blocked

    How to solve

  • Undefined reference to FFMPEG function despite linking via CMake

    8 mars, par MysticTortoise

    I am attempting to integrate FFMPEG's libav library into my project. I use CMake and want to build FFmpeg from source since I want to configure things specifically for my use case. I have compiled the files into .a archive static libraries which are included in my project, but i continually get an error:

    CMakeFiles/ffmpegtest.dir/main.cpp.obj:main.cpp:(.text+0xc): undefined reference to avformat_alloc_context

    I've tried a variety of solutions online but none seem to work. I've stripped the project down to the bare minimum and yet it continues to produce this error.

    Here is my main.cpp

    extern "C" {
        #include frame.h>
        #include mem.h>
        #include avcodec.h>
        #include avformat.h>
    }
    
    int main(){
        avformat_alloc_context();
        return 0;
    }
    

    And my CMakeLists.txt

    cmake_minimum_required(VERSION 3.24)
    project(ffmpegtest)
    
    add_executable(ffmpegtest main.cpp)
    
    find_library(AVCODEC_LIB avcodec PATHS lib/ffmpeg/lib)
    find_library(AVFORMAT_LIB avformat PATHS lib/ffmpeg/lib)
    find_library(AVUTIL_LIB avutil PATHS lib/ffmpeg/lib)
    find_library(AVDEVICE_LIB avdevice PATHS lib/ffmpeg/lib)
    
    target_include_directories(ffmpegtest PRIVATE
       lib/ffmpeg/include
    )
    
    
    target_link_libraries(ffmpegtest
     ${AVCODEC_LIB}  ${AVFORMAT_LIB}  ${AVUTIL_LIB}  ${AVDEVICE_LIB}
    )
    

    And finally, the configure script I have setup to build FFmpeg (stripped down)

    ./configure \
    --disable-doc \
    --enable-static \
    --prefix=${ffmpegBuildDir}
    

    (where ffmpegBuildDir is set elsewhere in the script. I have copied the .a files from that ffmpegBuildDir and into the corresponding directory into my stripped down test case.)

    I don't know what could be causing issues here. What am I doing wrong?

    For additional info, here is the command that CMake spits out:

    C:\WINDOWS\system32\cmd.exe /C "cd . && C:\devkitPro\msys2\mingw32\bin\c++.exe   CMakeFiles/ffmpegtest.dir/main.cpp.obj -o ffmpegtest.exe -Wl,--out-implib,libffmpegtest.dll.a -Wl,--major-image-version,0,--minor-image-version,0  D:/Programming/ffmpegtest/lib/ffmpeg/lib/libavcodec.a  D:/Programming/ffmpegtest/lib/ffmpeg/lib/libavformat.a  D:/Programming/ffmpegtest/lib/ffmpeg/lib/libavutil.a  D:/Programming/ffmpegtest/lib/ffmpeg/lib/libavdevice.a  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
    C:/devkitPro/msys2/mingw32/bin/../lib/gcc/i686-w64-mingw32/14.2.0/../../../../i686-w64-mingw32/bin/ld.exe: CMakeFiles/ffmpegtest.dir/main.cpp.obj:main.cpp:(.text+0xc): undefined reference to avformat_alloc_context
    

    EDIT: Here is exactly what i get from doing nm libavformat.a | grep avformat_alloc_context

                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
    0000000000000390 T avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context
                     U avformat_alloc_context