Benutzer-Werkzeuge

Webseiten-Werkzeuge


ffmpeg

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
ffmpeg [2025/12/10 16:11]
jango [Transcode]
ffmpeg [2025/12/10 16:54] (aktuell)
jango
Zeile 1: Zeile 1:
-=====Stream=====+=====CLI===== 
 + 
 +====Stream====
  
 Mit [[vlc|VLC]] kann man auch direkt streamen. Mit [[vlc|VLC]] kann man auch direkt streamen.
Zeile 36: Zeile 38:
 </code> </code>
  
-=====Convert=====+====Convert====
  
 https://bytescout.com/blog/2016/12/ffmpeg-command-lines-convert-various-video-formats.html https://bytescout.com/blog/2016/12/ffmpeg-command-lines-convert-various-video-formats.html
Zeile 66: Zeile 68:
 </code> </code>
  
-=====Modify=====+====Modify====
  
 <code> <code>
Zeile 350: Zeile 352:
  
 ====Transcode==== ====Transcode====
 +
 +===Video to Video===
  
 <code c++> <code c++>
Zeile 654: Zeile 658:
  
 # optional: -lbcrypt # optional: -lbcrypt
 +</code>
 +
 +<code>
 +main.exe test.mp4 test.mkv
 +</code>
 +
 +===Video to Audio===
 +
 +<code c++>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 + 
 +extern "C" {
 +#include <libavformat/avformat.h>
 +#include <libavcodec/avcodec.h>
 +#include <libavutil/avutil.h>
 +#include <libavutil/opt.h>
 +#include <libavutil/channel_layout.h>
 +#include <libavutil/samplefmt.h>
 +#include <libavutil/audio_fifo.h>
 +#include <libswresample/swresample.h>
 +}
 + 
 +static std::string fferr(int e) {
 +    char buf[AV_ERROR_MAX_STRING_SIZE] = {0};
 +    av_strerror(e, buf, sizeof(buf));
 +    return buf;
 +}
 + 
 +static int encode_and_write_audio(AVCodecContext* enc, AVFrame* frame, AVFormatContext* ofmt,
 +                                  AVStream* out_st, AVPacket* pkt)
 +{
 +    int ret = avcodec_send_frame(enc, frame);
 +    if (ret < 0) return ret;
 + 
 +    while (true) {
 +        ret = avcodec_receive_packet(enc, pkt);
 +        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return 0;
 +        if (ret < 0) return ret;
 + 
 +        av_packet_rescale_ts(pkt, enc->time_base, out_st->time_base);
 +        pkt->stream_index = out_st->index;
 + 
 +        ret = av_interleaved_write_frame(ofmt, pkt);
 +        av_packet_unref(pkt);
 +        if (ret < 0) return ret;
 +    }
 +}
 + 
 +int main(int argc, char** argv) {
 +    if (argc < 3) {
 +        std::cerr << "Usage: mp4_to_mp3.exe <infile> <outfile.mp3>\n";
 +        return 1;
 +    }
 + 
 +    const char* in_filename  = argv[1];
 +    const char* out_filename = argv[2];
 + 
 +    AVFormatContext* ifmt = nullptr;
 +    AVFormatContext* ofmt = nullptr;
 + 
 +    AVCodecContext* dec = nullptr;
 +    AVCodecContext* enc = nullptr;
 +    SwrContext* swr = nullptr;
 +    AVAudioFifo* fifo = nullptr;
 + 
 +    AVPacket* ipkt = av_packet_alloc();
 +    AVPacket* opkt = av_packet_alloc();
 +    AVFrame*  frame = av_frame_alloc();
 +    AVFrame*  out_frame = av_frame_alloc();
 + 
 +    if (!ipkt || !opkt || !frame || !out_frame) {
 +        std::cerr << "OOM\n";
 +        return 1;
 +    }
 + 
 +    int ret = avformat_open_input(&ifmt, in_filename, nullptr, nullptr);
 +    if (ret < 0) { std::cerr << "open input: " << fferr(ret) << "\n"; return 1; }
 + 
 +    ret = avformat_find_stream_info(ifmt, nullptr);
 +    if (ret < 0) { std::cerr << "stream info: " << fferr(ret) << "\n"; return 1; }
 + 
 +    int a_si = av_find_best_stream(ifmt, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
 +    if (a_si < 0) { std::cerr << "No audio stream.\n"; return 1; }
 + 
 +    AVStream* in_st = ifmt->streams[a_si];
 + 
 +    // --- decoder ---
 +    const AVCodec* adec = avcodec_find_decoder(in_st->codecpar->codec_id);
 +    if (!adec) { std::cerr << "No audio decoder.\n"; return 1; }
 + 
 +    dec = avcodec_alloc_context3(adec);
 +    if (!dec) { std::cerr << "alloc dec failed\n"; return 1; }
 + 
 +    ret = avcodec_parameters_to_context(dec, in_st->codecpar);
 +    if (ret < 0) { std::cerr << "par->ctx: " << fferr(ret) << "\n"; return 1; }
 + 
 +    ret = avcodec_open2(dec, adec, nullptr);
 +    if (ret < 0) { std::cerr << "open dec: " << fferr(ret) << "\n"; return 1; }
 + 
 +    // --- output context (.mp3) ---
 +    ret = avformat_alloc_output_context2(&ofmt, nullptr, "mp3", out_filename);
 +    if (ret < 0 || !ofmt) { std::cerr << "alloc output: " << fferr(ret) << "\n"; return 1; }
 + 
 +    AVStream* out_st = avformat_new_stream(ofmt, nullptr);
 +    if (!out_st) { std::cerr << "new stream failed\n"; return 1; }
 + 
 +    // --- encoder (prefer libmp3lame) ---
 +    const AVCodec* aenc = avcodec_find_encoder_by_name("libmp3lame");
 +    if (!aenc) aenc = avcodec_find_encoder(AV_CODEC_ID_MP3);
 +    if (!aenc) {
 +        std::cerr << "No MP3 encoder found. Your FFmpeg is missing libmp3lame encoder.\n";
 +        return 1;
 +    }
 + 
 +    enc = avcodec_alloc_context3(aenc);
 +    if (!enc) { std::cerr << "alloc enc failed\n"; return 1; }
 + 
 +    enc->bit_rate = 192000;
 +    enc->sample_rate = dec->sample_rate > 0 ? dec->sample_rate : 44100;
 + 
 +/*
 +    // channel layout (old-style, works on many FFmpeg builds; may be deprecated)
 +    uint64_t in_ch_layout = dec->channel_layout;
 +    if (!in_ch_layout) in_ch_layout = av_get_default_channel_layout(dec->channels);
 + 
 +    enc->channel_layout = in_ch_layout;
 +    enc->channels = av_get_channel_layout_nb_channels(enc->channel_layout);
 + */
 + AVChannelLayout in_layout;
 +av_channel_layout_default(&in_layout, 2);              // fallback stereo
 +if (dec->ch_layout.nb_channels > 0) {
 +    av_channel_layout_copy(&in_layout, &dec->ch_layout);
 +}
 +
 +// encoder layout = input layout
 +av_channel_layout_copy(&enc->ch_layout, &in_layout);
 +
 +// wenn du irgendwo "channels" brauchst:
 +int out_channels = enc->ch_layout.nb_channels;
 + 
 +    // pick a supported sample format
 +    enc->sample_fmt = (aenc->sample_fmts && aenc->sample_fmts[0] != AV_SAMPLE_FMT_NONE)
 +                        ? aenc->sample_fmts[0]
 +                        : AV_SAMPLE_FMT_S16P;
 + 
 +    enc->time_base = AVRational{1, enc->sample_rate};
 + 
 +    if (ofmt->oformat->flags & AVFMT_GLOBALHEADER)
 +        enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 + 
 +    ret = avcodec_open2(enc, aenc, nullptr);
 +    if (ret < 0) { std::cerr << "open enc: " << fferr(ret) << "\n"; return 1; }
 + 
 +    ret = avcodec_parameters_from_context(out_st->codecpar, enc);
 +    if (ret < 0) { std::cerr << "ctx->par: " << fferr(ret) << "\n"; return 1; }
 +    out_st->time_base = enc->time_base;
 + 
 +/* 
 +    // --- swr (convert input audio to encoder format) ---
 +    swr = swr_alloc_set_opts(nullptr,
 +                             (int64_t)enc->channel_layout, enc->sample_fmt, enc->sample_rate,
 +                             (int64_t)in_ch_layout,       dec->sample_fmt, dec->sample_rate,
 +                             0, nullptr);
 +    if (!swr) { std::cerr << "swr_alloc_set_opts failed\n"; return 1; }
 +*/
 +ret = swr_alloc_set_opts2(&swr,
 +                          &enc->ch_layout, enc->sample_fmt, enc->sample_rate,
 +                          &in_layout,      dec->sample_fmt, dec->sample_rate,
 +                          0, nullptr);
 +if (ret < 0) { std::cerr << "swr_alloc_set_opts2: " << fferr(ret) << "\n"; return 1; }
 + 
 +    ret = swr_init(swr);
 +    if (ret < 0) { std::cerr << "swr_init: " << fferr(ret) << "\n"; return 1; }
 + 
 +    //fifo = av_audio_fifo_alloc(enc->sample_fmt, enc->channels, 1);
 + fifo = av_audio_fifo_alloc(enc->sample_fmt, enc->ch_layout.nb_channels, 1);
 +    if (!fifo) { std::cerr << "audio fifo alloc failed\n"; return 1; }
 + 
 +    // --- write header ---
 +    if (!(ofmt->oformat->flags & AVFMT_NOFILE)) {
 +        ret = avio_open(&ofmt->pb, out_filename, AVIO_FLAG_WRITE);
 +        if (ret < 0) { std::cerr << "avio_open: " << fferr(ret) << "\n"; return 1; }
 +    }
 + 
 +    ret = avformat_write_header(ofmt, nullptr);
 +    if (ret < 0) { std::cerr << "write_header: " << fferr(ret) << "\n"; return 1; }
 + 
 +    int frame_size = (enc->frame_size > 0) ? enc->frame_size : 1152; // MP3 typical
 +    int64_t samples_written = 0;
 + 
 +    auto push_converted_to_fifo = [&](AVFrame* inframe) -> int {
 +        int out_nb = (int)av_rescale_rnd(
 +            swr_get_delay(swr, dec->sample_rate) + inframe->nb_samples,
 +            enc->sample_rate, dec->sample_rate, AV_ROUND_UP);
 + 
 +        uint8_t** conv = nullptr;
 +        
 + //int ret2 = av_samples_alloc_array_and_samples(&conv, nullptr, enc->channels, out_nb, enc->sample_fmt, 0);
 + int ret2 = av_samples_alloc_array_and_samples(&conv, nullptr, enc->ch_layout.nb_channels, out_nb, enc->sample_fmt, 0);
 +
 +        if (ret2 < 0) return ret2;
 + 
 +        int conv_samp = swr_convert(swr, conv, out_nb,
 +                                   (const uint8_t**)inframe->extended_data, inframe->nb_samples);
 +        if (conv_samp < 0) { av_freep(&conv[0]); av_freep(&conv); return conv_samp; }
 + 
 +        ret2 = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + conv_samp);
 +        if (ret2 < 0) { av_freep(&conv[0]); av_freep(&conv); return ret2; }
 + 
 +        av_audio_fifo_write(fifo, (void**)conv, conv_samp);
 + 
 +        av_freep(&conv[0]);
 +        av_freep(&conv);
 +        return 0;
 +    };
 + 
 +    auto pop_fifo_encode = [&](int nb) -> int {
 +        av_frame_unref(out_frame);
 +        out_frame->nb_samples = nb;
 +        out_frame->format = enc->sample_fmt;
 +        
 + //out_frame->channel_layout = enc->channel_layout;
 +        av_channel_layout_uninit(&out_frame->ch_layout);
 + av_channel_layout_copy(&out_frame->ch_layout, &enc->ch_layout);
 +
 + out_frame->sample_rate = enc->sample_rate;
 + 
 +        int r2 = av_frame_get_buffer(out_frame, 0);
 +        if (r2 < 0) return r2;
 + 
 +        r2 = av_frame_make_writable(out_frame);
 +        if (r2 < 0) return r2;
 + 
 +        int got = av_audio_fifo_read(fifo, (void**)out_frame->data, nb);
 +        if (got != nb) return AVERROR(EIO);
 + 
 +        out_frame->pts = samples_written;
 +        samples_written += nb;
 + 
 +        return encode_and_write_audio(enc, out_frame, ofmt, out_st, opkt);
 +    };
 + 
 +    // --- main loop ---
 +    while ((ret = av_read_frame(ifmt, ipkt)) >= 0) {
 +        if (ipkt->stream_index != a_si) {
 +            av_packet_unref(ipkt);
 +            continue;
 +        }
 + 
 +        ret = avcodec_send_packet(dec, ipkt);
 +        av_packet_unref(ipkt);
 +        if (ret < 0) { std::cerr << "send_packet: " << fferr(ret) << "\n"; return 1; }
 + 
 +        while (true) {
 +            ret = avcodec_receive_frame(dec, frame);
 +            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break;
 +            if (ret < 0) { std::cerr << "receive_frame: " << fferr(ret) << "\n"; return 1; }
 + 
 +            ret = push_converted_to_fifo(frame);
 +            av_frame_unref(frame);
 +            if (ret < 0) { std::cerr << "convert: " << fferr(ret) << "\n"; return 1; }
 + 
 +            while (av_audio_fifo_size(fifo) >= frame_size) {
 +                ret = pop_fifo_encode(frame_size);
 +                if (ret < 0) { std::cerr << "encode: " << fferr(ret) << "\n"; return 1; }
 +            }
 +        }
 +    }
 + 
 +    // flush decoder
 +    avcodec_send_packet(dec, nullptr);
 +    while (true) {
 +        ret = avcodec_receive_frame(dec, frame);
 +        if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) break;
 +        if (ret < 0) break;
 + 
 +        ret = push_converted_to_fifo(frame);
 +        av_frame_unref(frame);
 +        if (ret < 0) break;
 +    }
 + 
 +    // drain fifo (last partial)
 +    while (av_audio_fifo_size(fifo) > 0) {
 +        int nb = std::min(av_audio_fifo_size(fifo), frame_size);
 +        ret = pop_fifo_encode(nb);
 +        if (ret < 0) { std::cerr << "encode tail: " << fferr(ret) << "\n"; break; }
 +    }
 + 
 +    // flush encoder
 +    ret = encode_and_write_audio(enc, nullptr, ofmt, out_st, opkt);
 +    if (ret < 0) std::cerr << "flush enc: " << fferr(ret) << "\n";
 + 
 +    av_write_trailer(ofmt);
 + 
 +    // cleanup
 +    av_audio_fifo_free(fifo);
 +    swr_free(&swr);
 +    avcodec_free_context(&dec);
 +    avcodec_free_context(&enc);
 + 
 +    av_frame_free(&frame);
 +    av_frame_free(&out_frame);
 +    av_packet_free(&ipkt);
 +    av_packet_free(&opkt);
 + 
 +    avformat_close_input(&ifmt);
 +    if (ofmt && !(ofmt->oformat->flags & AVFMT_NOFILE)) avio_closep(&ofmt->pb);
 +    avformat_free_context(ofmt);
 + 
 +    return 0;
 +}
 +</code>
 +
 +<code>
 +g++ -std=c++17 -O2 main.cpp -o main.exe -IC:\chroot\ffmpeg\include -LC:\chroot\ffmpeg\lib -lavformat -lavcodec -lavutil -lswresample -lws2_32 -lsecur32 
 +
 +# optional: -lbcrypt
 +</code>
 +
 +<code>
 +main.exe test.mp4 test.mp3
 </code> </code>
 =====Links===== =====Links=====
ffmpeg.1765379476.txt.gz · Zuletzt geändert: 2025/12/10 16:11 von jango