Newest 'ffmpeg' Questions - Stack Overflow

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

Les articles publiés sur le site

  • Extract motion vectors from x265 (HEVC) encoded video with ffmpeg/libavcodec ?

    3 juillet, par John Allard

    I know that one can extract the motion vectors from an h264 encoded via by first setting the flag

    av_dict_set(&opts, "flags2", "+export_mvs", 0);
    

    then you can query the side-data for the motion vectors by doing this

    sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS);
    

    When I looked online to see if you can do something similar with HEVC encoded videos, I wasn't able to find any information. All I found was this by the definition of "AV_FRAME_DATA_MOTION_VECTORS"

    Motion vectors exported by some codecs (on demand through the export_mvs flag set in the libavcodec AVCodecContext flags2 option).

    The data is the AVMotionVector struct defined in libavutil/motion_vector.h.

    but there was no information on exactly which codecs export this motion vector information. How would I go about finding this out?

  • How to comp portion of first frame onto rest of video without re-encoding ? [closed]

    2 juillet, par jonathan

    I am working for a company recording educational screencasts using Goodnotes. The first frame looks fine, but as I work on the document, the page number pops up on the bottom left.

    My bosses don't like this, so I've been trying to find a way to fix it on the screencast, since I can't find a way to turn it off in Goodnotes.

    My current solution is taking a screenshot of the clean frame and using Gimp to crop out all but a small rectangle around where the page number would be, exporting that as a PNG and using ffmpeg to overlay that. The resulting image looks great and my bosses approve, but the script takes time to run since it needs to reencode. I'm wondering if there's a way to do this all with ffmpeg and run it with the -c copy flag since the first frame is clean. Please let me know if this is even possible.

  • Use FFmpeg to create MPEG-DASH files

    2 juillet, par angel_30

    I know using ffmpeg, we can create MPEG-DASH ready files, including the segments and the .mpd manifest file. For instance, I'm trying this command which works:

    ffmpeg -re -i .\video-h264.mkv -map 0 -map 0 -c:a aac -c:v libx264 -b:v:0 800k -b:v:1 300k -s:v:1 320x170 -profile:v:1 baseline -profile:v:0 main -bf 1 -keyint_min 120 -g 120 -sc_threshold 0 -b_strategy 0 -ar:a:1 22050 -use_timeline 1 -use_template 1 -window_size 5 -adaptation_sets "id=0,streams=v id=1,streams=a" -f dash out.mpd
    

    But I don't want to segment the video- so a simpler version where we have multiple versions of the whole video, no chunks. Does MPEG-DASH allow it? If so, how can I use ffmpeg to do it without creating the chunks?

  • ffmpeg dshow - Getting duplicate/dropped frames, I'm not doing anything [closed]

    30 juin, par ENunn

    I'm messing around with recording my capture card with ffmpeg. No matter what I do I get duplicate and dropped frames. d

    I'm not even doing anything on my computer. Is there a fix for this at all? Here's my command.

    ffmpeg -hide_banner -rtbufsize 2G -f dshow -video_size 2560x1440 -framerate 60.0002 -pix_fmt bgr24 -video_pin_name 0 -audio_pin_name 1 -i video="AVerMedia HD Capture GC573 1":audio="AVerMedia HD Capture GC573 1" -async 1 -rtbufsize 1M -f dshow -sample_rate 48000 -i audio="Digital Audio (S/PDIF) (Sound Blaster X-Fi Xtreme Audio)" -map 0 -map 1 -colorspace:v "bt709" -color_primaries:v "bt709" -color_trc:v "bt709" -color_range:v "tv" -c:v hevc_nvenc -pix_fmt yuv444p16le -gpu any -g 30 -rc vbr -cq 16 -qmin 16 -qmax 16 -b:v 0K -b_ref_mode 1 -spatial_aq 1 -temporal_aq 1 -preset p7 -c:a copy -f segment -segment_time 9999999999 -strftime 1 "F:\ffmpeg recordings%%Y-%%m-%%d_%%H-%%M-%%S.mkv"

  • C++/FFmpeg VLC doesn't play 5.1 audio output

    30 juin, par widgg

    I'm trying to convert audio streams to AAC in C++. FFplay plays everything fine (now) but VLC still has problems with one particular situation: 5.1(side). FFplay only plays it if I filter 5.1(side) to 5.1. Filtering to stereo or mono works well and as expected.

    My setup right now is:

    • send packet
    • receive audio AVFrame
    • apply filter
    • resample to produce output AVFrame with 1024 samples (required by AAC)
    • send new audio frame
    • receive audio packet

    Weirdly enough, using FFmpeg's CLI converts my file properly.

    ffmpeg -i  test.mp4
    

    But FFprobe tells me that the audio stream is now 6 channels instead of 5.1(side) or 5.1. I did try to set AAC to 6 channels in both the AVStream and the AVCodecContext. Setting it in the AVStream doesn't change anything in FFprobe and the AVCodecContext for AAC doesn't allow it.

    FFprobe of the audio stream in the source is:

    ac3 (AC-3 / 0x332D4341), 48000 Hz, 5.1(side), fltp, 384 kb/s
    

    FFprobe of the file created with FFmpeg's CLI:

    aac (LC) (mp4a / 0x6134706D), 48000 Hz, 6 channels, fltp, 395 kb/s (default)
    

    FFprobe of my current version:

    aac (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 321 kb/s (default)
    

    Update 1

    Here's how the filter is created (removed error handling code to make it shorter and more compact):

    struct FilterInfo {
        const AVCodecContext *srcContext, *sinkContext;
    };
    
    struct Filter {
        AVFilterGraph* graph = avfilter_graph_alloc();
        AVFilterContext* src, sink;
    };
    
    std::string getLayoutName(const AVChannelLayout* layout) {
        char layoutName[256];
        auto ret = av_channel_layout_describe(layout, layoutName, 256);
        return std::string(layoutName, ret);
    }
    
    std::string getFilterArgs(const FilterInfo& info) {
        const auto layout = &info.sinkContext->ch_layout;
        std::string dstLayout = getLayoutName(layout);
    
        std::string chans("0"sv);
        for (int c = 1; c < layout->nb_channels; ++c) {
            chans = std::format("{}|{}"sv, chans, c);
        }
        return std::format("channelmap={}:{}"sv, chans, dstLayout);
    }
    
    AVFilterContext* createSrcFilterContext(
        const AVCodecContext* cctx, AVFilterGraph* graph) {
        //
        std::string layout=getLayoutName(&cctx->ch_layout);
    
        const auto args = std::format("time_base={}/{}:sample_rate={}:sample_fmt={}:channel_layout={}"sv,
            cctx->time_base.num, cctx->time_base.den, cctx->sample_rate,
            av_get_sample_fmt_name(cctx->sample_fmt), layout);
    
        const AVFilter* filt = avfilter_get_by_name("abuffer");
        AVFilterContext* fctx = nullptr;
        avfilter_graph_create_filter(&fctx, filt, "in", args.c_str(), nullptr, graph);
        return fctx;
    }
    
    AVFilterContext* createSinkFilterContext(
        const AVCodecContext* cctx, AVFilterGraph* graph) {
        //
        std::string layout = getLayoutName(&cctx->ch_layout));
    
        const AVFilter* filt = avfilter_get_by_name("abuffersink");
        AVFilterContext* fctx = nullptr;
        avfilter_graph_create_filter(&fctx, filt, "out", nullptr, nullptr, graph);
        av_opt_set(fctx, "ch_layouts", layout.c_str(), AV_OPT_SEARCH_CHILDREN);
    
        const AVSampleFormat sampleFmts[] = {cctx->sample_fmt, AV_SAMPLE_FMT_NONE};
        av_opt_set_int_list(fctx, "sample_fmts", sampleFmts, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
    
        const int sampleRates[] = {cctx->sample_rate, -1};
        av_opt_set_int_list(fctx, "sample_rates", sampleRates, -1, AV_OPT_SEARCH_CHILDREN);
        return fctx;
    }
    
    Filter create(const FilterInfo& info) {
        std::string filterArgs = getFilterArgs(info);
    
        filter.graph = avfilter_graph_alloc();
        filter.src, createSrcFilterContext(info.srcContext, filter.graph);
        filter.sink, createSinkFilterContext(info.sinkContext, filter.graph);
    
        AVFilterInOut* inputs = avfilter_inout_alloc();
        AVFilterInOut* outputs = avfilter_inout_alloc();
    
        outputs->name = av_strdup("in");
        outputs->filter_ctx = filter.src.get();
        outputs->pad_idx = 0;
        outputs->next = nullptr;
    
        inputs->name = av_strdup("out");
        inputs->filter_ctx = filter.sink.get();
        inputs->pad_idx = 0;
        inputs->next = nullptr;
    
        avfilter_graph_parse_ptr(filter.graph, filterArgs.c_str(), &inputs, &outputs, nullptr);
        avfilter_inout_free(&inputs);
        avfilter_inout_free(&outputs);
    
        avfilter_graph_config(filter.graph, nullptr);
        return filter; // didn't fail, but not needed
    }
    

    This is how it gets executed:

    
    AVFrame* receiveFrame(Filter& f) {
        AVFrame* frm = av_frame_alloc();
        if (int ret = av_buffersink_get_frame(f.sink, frm); ret < 0) {
            if (ret == AVERROR(EAGAIN)) {
                return nullptr;
            }
            else {
                // throw error
            }
        }
        return frm;
    }
    
    void filteredFrameToProcess(Filter& f, SomeFrameQueue& queue) {
        while (true) {
            if (auto frm = receiveFrame(f); frm) {
                queue.emplace_back(frm);
            }
            else {
                break;
            }
        }
    }
    
    void filter(Filter& f, SomeFrameQueue& dst, SomeFrameQueue& src) {
        filteredFrameToProcess(f, dst); 
        if (!src.empty()) {
            av_buffersrc_write_frame(f.src, src.front());
            src.pop_front();
        }
        filteredFrameToProcess(f, dst);
    }