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:33]
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 668: Zeile 670:
 #include <string> #include <string>
 #include <algorithm> #include <algorithm>
 + 
 extern "C" { extern "C" {
 #include <libavformat/avformat.h> #include <libavformat/avformat.h>
Zeile 679: Zeile 681:
 #include <libswresample/swresample.h> #include <libswresample/swresample.h>
 } }
 + 
 static std::string fferr(int e) { static std::string fferr(int e) {
     char buf[AV_ERROR_MAX_STRING_SIZE] = {0};     char buf[AV_ERROR_MAX_STRING_SIZE] = {0};
Zeile 685: Zeile 687:
     return buf;     return buf;
 } }
 + 
 static int encode_and_write_audio(AVCodecContext* enc, AVFrame* frame, AVFormatContext* ofmt, static int encode_and_write_audio(AVCodecContext* enc, AVFrame* frame, AVFormatContext* ofmt,
                                   AVStream* out_st, AVPacket* pkt)                                   AVStream* out_st, AVPacket* pkt)
Zeile 691: Zeile 693:
     int ret = avcodec_send_frame(enc, frame);     int ret = avcodec_send_frame(enc, frame);
     if (ret < 0) return ret;     if (ret < 0) return ret;
 + 
     while (true) {     while (true) {
         ret = avcodec_receive_packet(enc, pkt);         ret = avcodec_receive_packet(enc, pkt);
         if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return 0;         if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return 0;
         if (ret < 0) return ret;         if (ret < 0) return ret;
 + 
         av_packet_rescale_ts(pkt, enc->time_base, out_st->time_base);         av_packet_rescale_ts(pkt, enc->time_base, out_st->time_base);
         pkt->stream_index = out_st->index;         pkt->stream_index = out_st->index;
 + 
         ret = av_interleaved_write_frame(ofmt, pkt);         ret = av_interleaved_write_frame(ofmt, pkt);
         av_packet_unref(pkt);         av_packet_unref(pkt);
Zeile 705: Zeile 707:
     }     }
 } }
 + 
 int main(int argc, char** argv) { int main(int argc, char** argv) {
     if (argc < 3) {     if (argc < 3) {
Zeile 711: Zeile 713:
         return 1;         return 1;
     }     }
 + 
     const char* in_filename  = argv[1];     const char* in_filename  = argv[1];
     const char* out_filename = argv[2];     const char* out_filename = argv[2];
 + 
     AVFormatContext* ifmt = nullptr;     AVFormatContext* ifmt = nullptr;
     AVFormatContext* ofmt = nullptr;     AVFormatContext* ofmt = nullptr;
 + 
     AVCodecContext* dec = nullptr;     AVCodecContext* dec = nullptr;
     AVCodecContext* enc = nullptr;     AVCodecContext* enc = nullptr;
     SwrContext* swr = nullptr;     SwrContext* swr = nullptr;
     AVAudioFifo* fifo = nullptr;     AVAudioFifo* fifo = nullptr;
 + 
     AVPacket* ipkt = av_packet_alloc();     AVPacket* ipkt = av_packet_alloc();
     AVPacket* opkt = av_packet_alloc();     AVPacket* opkt = av_packet_alloc();
     AVFrame*  frame = av_frame_alloc();     AVFrame*  frame = av_frame_alloc();
     AVFrame*  out_frame = av_frame_alloc();     AVFrame*  out_frame = av_frame_alloc();
 + 
     if (!ipkt || !opkt || !frame || !out_frame) {     if (!ipkt || !opkt || !frame || !out_frame) {
         std::cerr << "OOM\n";         std::cerr << "OOM\n";
         return 1;         return 1;
     }     }
 + 
     int ret = avformat_open_input(&ifmt, in_filename, nullptr, nullptr);     int ret = avformat_open_input(&ifmt, in_filename, nullptr, nullptr);
     if (ret < 0) { std::cerr << "open input: " << fferr(ret) << "\n"; return 1; }     if (ret < 0) { std::cerr << "open input: " << fferr(ret) << "\n"; return 1; }
 + 
     ret = avformat_find_stream_info(ifmt, nullptr);     ret = avformat_find_stream_info(ifmt, nullptr);
     if (ret < 0) { std::cerr << "stream info: " << fferr(ret) << "\n"; return 1; }     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);     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; }     if (a_si < 0) { std::cerr << "No audio stream.\n"; return 1; }
 + 
     AVStream* in_st = ifmt->streams[a_si];     AVStream* in_st = ifmt->streams[a_si];
 + 
     // --- decoder ---     // --- decoder ---
     const AVCodec* adec = avcodec_find_decoder(in_st->codecpar->codec_id);     const AVCodec* adec = avcodec_find_decoder(in_st->codecpar->codec_id);
     if (!adec) { std::cerr << "No audio decoder.\n"; return 1; }     if (!adec) { std::cerr << "No audio decoder.\n"; return 1; }
 + 
     dec = avcodec_alloc_context3(adec);     dec = avcodec_alloc_context3(adec);
     if (!dec) { std::cerr << "alloc dec failed\n"; return 1; }     if (!dec) { std::cerr << "alloc dec failed\n"; return 1; }
 + 
     ret = avcodec_parameters_to_context(dec, in_st->codecpar);     ret = avcodec_parameters_to_context(dec, in_st->codecpar);
     if (ret < 0) { std::cerr << "par->ctx: " << fferr(ret) << "\n"; return 1; }     if (ret < 0) { std::cerr << "par->ctx: " << fferr(ret) << "\n"; return 1; }
 + 
     ret = avcodec_open2(dec, adec, nullptr);     ret = avcodec_open2(dec, adec, nullptr);
     if (ret < 0) { std::cerr << "open dec: " << fferr(ret) << "\n"; return 1; }     if (ret < 0) { std::cerr << "open dec: " << fferr(ret) << "\n"; return 1; }
 + 
     // --- output context (.mp3) ---     // --- output context (.mp3) ---
     ret = avformat_alloc_output_context2(&ofmt, nullptr, "mp3", out_filename);     ret = avformat_alloc_output_context2(&ofmt, nullptr, "mp3", out_filename);
     if (ret < 0 || !ofmt) { std::cerr << "alloc output: " << fferr(ret) << "\n"; return 1; }     if (ret < 0 || !ofmt) { std::cerr << "alloc output: " << fferr(ret) << "\n"; return 1; }
 + 
     AVStream* out_st = avformat_new_stream(ofmt, nullptr);     AVStream* out_st = avformat_new_stream(ofmt, nullptr);
     if (!out_st) { std::cerr << "new stream failed\n"; return 1; }     if (!out_st) { std::cerr << "new stream failed\n"; return 1; }
 + 
     // --- encoder (prefer libmp3lame) ---     // --- encoder (prefer libmp3lame) ---
     const AVCodec* aenc = avcodec_find_encoder_by_name("libmp3lame");     const AVCodec* aenc = avcodec_find_encoder_by_name("libmp3lame");
Zeile 771: Zeile 773:
         return 1;         return 1;
     }     }
 + 
     enc = avcodec_alloc_context3(aenc);     enc = avcodec_alloc_context3(aenc);
     if (!enc) { std::cerr << "alloc enc failed\n"; return 1; }     if (!enc) { std::cerr << "alloc enc failed\n"; return 1; }
 + 
     enc->bit_rate = 192000;     enc->bit_rate = 192000;
     enc->sample_rate = dec->sample_rate > 0 ? dec->sample_rate : 44100;     enc->sample_rate = dec->sample_rate > 0 ? dec->sample_rate : 44100;
 +  
 +/*
     // channel layout (old-style, works on many FFmpeg builds; may be deprecated)     // channel layout (old-style, works on many FFmpeg builds; may be deprecated)
     uint64_t in_ch_layout = dec->channel_layout;     uint64_t in_ch_layout = dec->channel_layout;
     if (!in_ch_layout) in_ch_layout = av_get_default_channel_layout(dec->channels);     if (!in_ch_layout) in_ch_layout = av_get_default_channel_layout(dec->channels);
 + 
     enc->channel_layout = in_ch_layout;     enc->channel_layout = in_ch_layout;
     enc->channels = av_get_channel_layout_nb_channels(enc->channel_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     // pick a supported sample format
     enc->sample_fmt = (aenc->sample_fmts && aenc->sample_fmts[0] != AV_SAMPLE_FMT_NONE)     enc->sample_fmt = (aenc->sample_fmts && aenc->sample_fmts[0] != AV_SAMPLE_FMT_NONE)
                         ? aenc->sample_fmts[0]                         ? aenc->sample_fmts[0]
                         : AV_SAMPLE_FMT_S16P;                         : AV_SAMPLE_FMT_S16P;
 + 
     enc->time_base = AVRational{1, enc->sample_rate};     enc->time_base = AVRational{1, enc->sample_rate};
 + 
     if (ofmt->oformat->flags & AVFMT_GLOBALHEADER)     if (ofmt->oformat->flags & AVFMT_GLOBALHEADER)
         enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;         enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 + 
     ret = avcodec_open2(enc, aenc, nullptr);     ret = avcodec_open2(enc, aenc, nullptr);
     if (ret < 0) { std::cerr << "open enc: " << fferr(ret) << "\n"; return 1; }     if (ret < 0) { std::cerr << "open enc: " << fferr(ret) << "\n"; return 1; }
 + 
     ret = avcodec_parameters_from_context(out_st->codecpar, enc);     ret = avcodec_parameters_from_context(out_st->codecpar, enc);
     if (ret < 0) { std::cerr << "ctx->par: " << fferr(ret) << "\n"; return 1; }     if (ret < 0) { std::cerr << "ctx->par: " << fferr(ret) << "\n"; return 1; }
     out_st->time_base = enc->time_base;     out_st->time_base = enc->time_base;
 +  
 +/* 
     // --- swr (convert input audio to encoder format) ---     // --- swr (convert input audio to encoder format) ---
     swr = swr_alloc_set_opts(nullptr,     swr = swr_alloc_set_opts(nullptr,
Zeile 808: Zeile 824:
                              0, nullptr);                              0, nullptr);
     if (!swr) { std::cerr << "swr_alloc_set_opts failed\n"; return 1; }     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);     ret = swr_init(swr);
     if (ret < 0) { std::cerr << "swr_init: " << fferr(ret) << "\n"; return 1; }     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->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; }     if (!fifo) { std::cerr << "audio fifo alloc failed\n"; return 1; }
 + 
     // --- write header ---     // --- write header ---
     if (!(ofmt->oformat->flags & AVFMT_NOFILE)) {     if (!(ofmt->oformat->flags & AVFMT_NOFILE)) {
Zeile 820: Zeile 843:
         if (ret < 0) { std::cerr << "avio_open: " << fferr(ret) << "\n"; return 1; }         if (ret < 0) { std::cerr << "avio_open: " << fferr(ret) << "\n"; return 1; }
     }     }
 + 
     ret = avformat_write_header(ofmt, nullptr);     ret = avformat_write_header(ofmt, nullptr);
     if (ret < 0) { std::cerr << "write_header: " << fferr(ret) << "\n"; return 1; }     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     int frame_size = (enc->frame_size > 0) ? enc->frame_size : 1152; // MP3 typical
     int64_t samples_written = 0;     int64_t samples_written = 0;
 + 
     auto push_converted_to_fifo = [&](AVFrame* inframe) -> int {     auto push_converted_to_fifo = [&](AVFrame* inframe) -> int {
         int out_nb = (int)av_rescale_rnd(         int out_nb = (int)av_rescale_rnd(
             swr_get_delay(swr, dec->sample_rate) + inframe->nb_samples,             swr_get_delay(swr, dec->sample_rate) + inframe->nb_samples,
             enc->sample_rate, dec->sample_rate, AV_ROUND_UP);             enc->sample_rate, dec->sample_rate, AV_ROUND_UP);
 + 
         uint8_t** conv = nullptr;         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->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;         if (ret2 < 0) return ret2;
 + 
         int conv_samp = swr_convert(swr, conv, out_nb,         int conv_samp = swr_convert(swr, conv, out_nb,
                                    (const uint8_t**)inframe->extended_data, inframe->nb_samples);                                    (const uint8_t**)inframe->extended_data, inframe->nb_samples);
         if (conv_samp < 0) { av_freep(&conv[0]); av_freep(&conv); return conv_samp; }         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);         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; }         if (ret2 < 0) { av_freep(&conv[0]); av_freep(&conv); return ret2; }
 + 
         av_audio_fifo_write(fifo, (void**)conv, conv_samp);         av_audio_fifo_write(fifo, (void**)conv, conv_samp);
 + 
         av_freep(&conv[0]);         av_freep(&conv[0]);
         av_freep(&conv);         av_freep(&conv);
         return 0;         return 0;
     };     };
 + 
     auto pop_fifo_encode = [&](int nb) -> int {     auto pop_fifo_encode = [&](int nb) -> int {
         av_frame_unref(out_frame);         av_frame_unref(out_frame);
         out_frame->nb_samples = nb;         out_frame->nb_samples = nb;
         out_frame->format = enc->sample_fmt;         out_frame->format = enc->sample_fmt;
-        out_frame->channel_layout = enc->channel_layout; +         
-        out_frame->sample_rate = enc->sample_rate; + //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);         int r2 = av_frame_get_buffer(out_frame, 0);
         if (r2 < 0) return r2;         if (r2 < 0) return r2;
 + 
         r2 = av_frame_make_writable(out_frame);         r2 = av_frame_make_writable(out_frame);
         if (r2 < 0) return r2;         if (r2 < 0) return r2;
 + 
         int got = av_audio_fifo_read(fifo, (void**)out_frame->data, nb);         int got = av_audio_fifo_read(fifo, (void**)out_frame->data, nb);
         if (got != nb) return AVERROR(EIO);         if (got != nb) return AVERROR(EIO);
 + 
         out_frame->pts = samples_written;         out_frame->pts = samples_written;
         samples_written += nb;         samples_written += nb;
 + 
         return encode_and_write_audio(enc, out_frame, ofmt, out_st, opkt);         return encode_and_write_audio(enc, out_frame, ofmt, out_st, opkt);
     };     };
 + 
     // --- main loop ---     // --- main loop ---
     while ((ret = av_read_frame(ifmt, ipkt)) >= 0) {     while ((ret = av_read_frame(ifmt, ipkt)) >= 0) {
Zeile 878: Zeile 908:
             continue;             continue;
         }         }
 + 
         ret = avcodec_send_packet(dec, ipkt);         ret = avcodec_send_packet(dec, ipkt);
         av_packet_unref(ipkt);         av_packet_unref(ipkt);
         if (ret < 0) { std::cerr << "send_packet: " << fferr(ret) << "\n"; return 1; }         if (ret < 0) { std::cerr << "send_packet: " << fferr(ret) << "\n"; return 1; }
 + 
         while (true) {         while (true) {
             ret = avcodec_receive_frame(dec, frame);             ret = avcodec_receive_frame(dec, frame);
             if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break;             if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break;
             if (ret < 0) { std::cerr << "receive_frame: " << fferr(ret) << "\n"; return 1; }             if (ret < 0) { std::cerr << "receive_frame: " << fferr(ret) << "\n"; return 1; }
 + 
             ret = push_converted_to_fifo(frame);             ret = push_converted_to_fifo(frame);
             av_frame_unref(frame);             av_frame_unref(frame);
             if (ret < 0) { std::cerr << "convert: " << fferr(ret) << "\n"; return 1; }             if (ret < 0) { std::cerr << "convert: " << fferr(ret) << "\n"; return 1; }
 + 
             while (av_audio_fifo_size(fifo) >= frame_size) {             while (av_audio_fifo_size(fifo) >= frame_size) {
                 ret = pop_fifo_encode(frame_size);                 ret = pop_fifo_encode(frame_size);
Zeile 898: Zeile 928:
         }         }
     }     }
 + 
     // flush decoder     // flush decoder
     avcodec_send_packet(dec, nullptr);     avcodec_send_packet(dec, nullptr);
Zeile 905: Zeile 935:
         if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) break;         if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) break;
         if (ret < 0) break;         if (ret < 0) break;
 + 
         ret = push_converted_to_fifo(frame);         ret = push_converted_to_fifo(frame);
         av_frame_unref(frame);         av_frame_unref(frame);
         if (ret < 0) break;         if (ret < 0) break;
     }     }
 + 
     // drain fifo (last partial)     // drain fifo (last partial)
     while (av_audio_fifo_size(fifo) > 0) {     while (av_audio_fifo_size(fifo) > 0) {
Zeile 917: Zeile 947:
         if (ret < 0) { std::cerr << "encode tail: " << fferr(ret) << "\n"; break; }         if (ret < 0) { std::cerr << "encode tail: " << fferr(ret) << "\n"; break; }
     }     }
 + 
     // flush encoder     // flush encoder
     ret = encode_and_write_audio(enc, nullptr, ofmt, out_st, opkt);     ret = encode_and_write_audio(enc, nullptr, ofmt, out_st, opkt);
     if (ret < 0) std::cerr << "flush enc: " << fferr(ret) << "\n";     if (ret < 0) std::cerr << "flush enc: " << fferr(ret) << "\n";
 + 
     av_write_trailer(ofmt);     av_write_trailer(ofmt);
 + 
     // cleanup     // cleanup
     av_audio_fifo_free(fifo);     av_audio_fifo_free(fifo);
Zeile 929: Zeile 959:
     avcodec_free_context(&dec);     avcodec_free_context(&dec);
     avcodec_free_context(&enc);     avcodec_free_context(&enc);
 + 
     av_frame_free(&frame);     av_frame_free(&frame);
     av_frame_free(&out_frame);     av_frame_free(&out_frame);
     av_packet_free(&ipkt);     av_packet_free(&ipkt);
     av_packet_free(&opkt);     av_packet_free(&opkt);
 + 
     avformat_close_input(&ifmt);     avformat_close_input(&ifmt);
     if (ofmt && !(ofmt->oformat->flags & AVFMT_NOFILE)) avio_closep(&ofmt->pb);     if (ofmt && !(ofmt->oformat->flags & AVFMT_NOFILE)) avio_closep(&ofmt->pb);
     avformat_free_context(ofmt);     avformat_free_context(ofmt);
 + 
     return 0;     return 0;
 } }
Zeile 944: Zeile 974:
  
 <code> <code>
-g++ -std=c++17 -O2 mp4_to_mp3.cpp -o mp4_to_mp3.exe -IC:\chroot\ffmpeg\include -LC:\chroot\ffmpeg\lib -lavformat -lavcodec -lavutil -lswresample -lws2_32 -lsecur32 -lbcrypt+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>
  
ffmpeg.1765380802.txt.gz · Zuletzt geändert: 2025/12/10 16:33 von jango