Newest 'ffmpeg' Questions - Stack Overflow

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

Les articles publiés sur le site

  • 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
    
  • How to stream frames from ffmpeg to a process ?

    7 mars, par Vorac

    I would like to encrypt camera frames before transmitting. For that purpose the encrypting process needs to get the raw frames through some mode of IPC. I tried reading through the steaming API docs but got lost. This is an "what approach" question instead of a "working solution" one.