最新(2.44)FFmpeg音频播放 ----- 关键点swr_convert

14 篇文章 0 订阅

ffmpeg 版本:git clone 于 2014-12-02 ,版本接近2.44,在2.44和2.51之间

SDL版本:SDL 1.2(Centos 6.5软件库的相应版本)


       有些旧的ffmpeg播放音频示例中,会存在一些音频可以播放一些不能播放,其中一个我们需要考虑的原因和该注意的地方就是 av_decode_audiole类似函数所获的的AVFrame的格式是否是我们(SDL)所需要的,本例代码用来解决该问题,关键点在于swr_convert函数,代码及注释如下:


[cpp]  view plain  copy
  1. </pre><pre name="code" class="cpp">#include <libavcodec/avcodec.h>  
  2. #include <libavformat/avformat.h>  
  3. #include <libswscale/swscale.h>  
  4. #include <libswresample/swresample.h>  
  5. #include <libavutil/avstring.h>  
  6. #include <libavutil/pixfmt.h>  
  7. #include <libavutil/log.h>  
  8. #include <SDL/SDL.h>  
  9. #include <SDL/SDL_thread.h>  
  10. #include <stdio.h>  
  11. #include <math.h>  
  12.   
  13. #define SDL_AUDIO_BUFFER_SIZE 1024   
  14. #define MAX_AUDIOQ_SIZE (1 * 1024 * 1024)  
  15. #define FF_ALLOC_EVENT   (SDL_USEREVENT)  
  16. #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)  
  17. #define FF_QUIT_EVENT (SDL_USEREVENT + 2)  
  18.   
  19. //该字段存在于旧版本的ffmpeg中,此处粘贴过来使用,勿怪!  
  20. #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio  
  21.   
  22. typedef struct PacketQueue {  
  23.     AVPacketList *first_pkt, *last_pkt;  
  24.     int nb_packets;  
  25.     int size;  
  26.     SDL_mutex *mutex;  
  27.     SDL_cond *cond;  
  28. } PacketQueue;  
  29.   
  30. typedef struct VideoState {  
  31.     char filename[1024];  
  32.     AVFormatContext *ic;  
  33.     int videoStream, audioStream;  
  34.     AVStream *audio_st;  
  35.     AVFrame *audio_frame;  
  36.     PacketQueue audioq;  
  37.     unsigned int audio_buf_size;  
  38.     unsigned int audio_buf_index;  
  39.     AVPacket audio_pkt;  
  40.     uint8_t *audio_pkt_data;  
  41.     int audio_pkt_size;  
  42.     uint8_t *audio_buf;  
  43.     uint8_t *audio_buf1;  
  44.     DECLARE_ALIGNED(16,uint8_t,audio_buf2) [AVCODEC_MAX_AUDIO_FRAME_SIZE * 4];  
  45.     enum AVSampleFormat audio_src_fmt;  
  46.     enum AVSampleFormat audio_tgt_fmt;  
  47.     int audio_src_channels;  
  48.     int audio_tgt_channels;  
  49.     int64_t audio_src_channel_layout;  
  50.     int64_t audio_tgt_channel_layout;  
  51.     int audio_src_freq;  
  52.     int audio_tgt_freq;  
  53.     struct SwrContext *swr_ctx;  
  54.     SDL_Thread *parse_tid;  
  55.     int quit;  
  56. } VideoState;  
  57.   
  58. VideoState *global_video_state;  
  59.   
  60. void packet_queue_init(PacketQueue *q) {  
  61.     memset(q, 0, sizeof(PacketQueue));  
  62.     q->mutex = SDL_CreateMutex();  
  63.     q->cond = SDL_CreateCond();  
  64. }  
  65.   
  66. int packet_queue_put(PacketQueue *q, AVPacket *pkt) {  
  67.     AVPacketList *pkt1;  
  68.   
  69.     pkt1 = (AVPacketList *) av_malloc(sizeof(AVPacketList));  
  70.     if (!pkt1) {  
  71.         return -1;  
  72.     }  
  73.     pkt1->pkt = *pkt;  
  74.     pkt1->next = NULL;  
  75.   
  76.     SDL_LockMutex(q->mutex);  
  77.   
  78.     if (!q->last_pkt) {  
  79.         q->first_pkt = pkt1;  
  80.     } else {  
  81.         q->last_pkt->next = pkt1;  
  82.     }  
  83.   
  84.     q->last_pkt = pkt1;  
  85.     q->nb_packets++;  
  86.     q->size += pkt1->pkt.size;  
  87.     SDL_CondSignal(q->cond);  
  88.     SDL_UnlockMutex(q->mutex);  
  89.     return 0;  
  90. }  
  91.   
  92. static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {  
  93.     AVPacketList *pkt1;  
  94.     int ret;  
  95.   
  96.     SDL_LockMutex(q->mutex);  
  97.   
  98.     for (;;) {  
  99.         if (global_video_state->quit) {  
  100.             ret = -1;  
  101.             break;  
  102.         }  
  103.   
  104.         pkt1 = q->first_pkt;  
  105.         if (pkt1) {  
  106.             q->first_pkt = pkt1->next;  
  107.             if (!q->first_pkt) {  
  108.                 q->last_pkt = NULL;  
  109.             }  
  110.             q->nb_packets--;  
  111.             q->size -= pkt1->pkt.size;  
  112.             *pkt = pkt1->pkt;  
  113.   
  114.             av_free(pkt1);  
  115.             ret = 1;  
  116.             break;  
  117.         } else if (!block) {  
  118.             ret = 0;  
  119.             break;  
  120.         } else {  
  121.             SDL_CondWait(q->cond, q->mutex);  
  122.         }  
  123.     }  
  124.   
  125.     SDL_UnlockMutex(q->mutex);  
  126.   
  127.     return ret;  
  128. }  
  129.   
  130. int audio_decode_frame(VideoState *is) {  
  131.     int len1, len2, decoded_data_size;  
  132.     AVPacket *pkt = &is->audio_pkt;  
  133.     int got_frame = 0;  
  134.     int64_t dec_channel_layout;  
  135.     int wanted_nb_samples, resampled_data_size;  
  136.   
  137.     for (;;) {  
  138.         while (is->audio_pkt_size > 0) {  
  139.             if (!is->audio_frame) {  
  140.                 if (!(is->audio_frame = av_frame_alloc())) {  
  141.                     return AVERROR(ENOMEM);  
  142.                 }  
  143.             } else  
  144.                 av_frame_unref(is->audio_frame);  
  145.             /** 
  146.              * 当AVPacket中装得是音频时,有可能一个AVPacket中有多个AVFrame, 
  147.              * 而某些解码器只会解出第一个AVFrame,这种情况我们必须循环解码出后续AVFrame 
  148.              */  
  149.             len1 = avcodec_decode_audio4(is->audio_st->codec, is->audio_frame,  
  150.                     &got_frame, pkt);  
  151.             if (len1 < 0) {  
  152.                 // error, skip the frame  
  153.                 is->audio_pkt_size = 0;  
  154.                 break;  
  155.             }  
  156.   
  157.             is->audio_pkt_data += len1;  
  158.             is->audio_pkt_size -= len1;  
  159.   
  160.             if (!got_frame)  
  161.                 continue;  
  162.             //执行到这里我们得到了一个AVFrame  
  163.   
  164.             decoded_data_size = av_samples_get_buffer_size(NULL,  
  165.                     is->audio_frame->channels, is->audio_frame->nb_samples,  
  166.                     is->audio_frame->format, 1);  
  167.   
  168.             //得到这个AvFrame的声音布局,比如立体声  
  169.             dec_channel_layout =  
  170.                     (is->audio_frame->channel_layout  
  171.                             && is->audio_frame->channels  
  172.                                     == av_get_channel_layout_nb_channels(  
  173.                                             is->audio_frame->channel_layout)) ?  
  174.                             is->audio_frame->channel_layout :  
  175.                             av_get_default_channel_layout(  
  176.                                     is->audio_frame->channels);  
  177.   
  178.             //这个AVFrame每个声道的采样数  
  179.             wanted_nb_samples = is->audio_frame->nb_samples;  
  180.   
  181.   
  182.             /** 
  183.              * 接下来判断我们之前设置SDL时设置的声音格式(AV_SAMPLE_FMT_S16),声道布局, 
  184.              * 采样频率,每个AVFrame的每个声道采样数与 
  185.              * 得到的该AVFrame分别是否相同,如有任意不同,我们就需要swr_convert该AvFrame, 
  186.              * 然后才能符合之前设置好的SDL的需要,才能播放 
  187.              */  
  188.             if (is->audio_frame->format != is->audio_src_fmt  
  189.                     || dec_channel_layout != is->audio_src_channel_layout  
  190.                     || is->audio_frame->sample_rate != is->audio_src_freq  
  191.                     || (wanted_nb_samples != is->audio_frame->nb_samples  
  192.                             && !is->swr_ctx)) {  
  193.                 if (is->swr_ctx)  
  194.                     swr_free(&is->swr_ctx);  
  195.                 is->swr_ctx = swr_alloc_set_opts(NULL,  
  196.                         is->audio_tgt_channel_layout, is->audio_tgt_fmt,  
  197.                         is->audio_tgt_freq, dec_channel_layout,  
  198.                         is->audio_frame->format, is->audio_frame->sample_rate,  
  199.                         0, NULL);  
  200.                 if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {  
  201.                     fprintf(stderr, "swr_init() failed\n");  
  202.                     break;  
  203.                 }  
  204.                 is->audio_src_channel_layout = dec_channel_layout;  
  205.                 is->audio_src_channels = is->audio_st->codec->channels;  
  206.                 is->audio_src_freq = is->audio_st->codec->sample_rate;  
  207.                 is->audio_src_fmt = is->audio_st->codec->sample_fmt;  
  208.             }  
  209.   
  210.             /** 
  211.              * 如果上面if判断失败,就会初始化好swr_ctx,就会如期进行转换 
  212.              */  
  213.             if (is->swr_ctx) {  
  214.                 // const uint8_t *in[] = { is->audio_frame->data[0] };  
  215.                 const uint8_t **in =  
  216.                         (const uint8_t **) is->audio_frame->extended_data;  
  217.                 uint8_t *out[] = { is->audio_buf2 };  
  218.                 if (wanted_nb_samples != is->audio_frame->nb_samples) {  
  219.                     fprintf(stdout, "swr_set_compensation \n");  
  220.                     if (swr_set_compensation(is->swr_ctx,  
  221.                             (wanted_nb_samples - is->audio_frame->nb_samples)  
  222.                                     * is->audio_tgt_freq  
  223.                                     / is->audio_frame->sample_rate,  
  224.                             wanted_nb_samples * is->audio_tgt_freq  
  225.                                     / is->audio_frame->sample_rate) < 0) {  
  226.                         fprintf(stderr, "swr_set_compensation() failed\n");  
  227.                         break;  
  228.                     }  
  229.                 }  
  230.   
  231.                 /** 
  232.                  * 转换该AVFrame到设置好的SDL需要的样子,有些旧的代码示例最主要就是少了这一部分, 
  233.                  * 往往一些音频能播,一些不能播,这就是原因,比如有些源文件音频恰巧是AV_SAMPLE_FMT_S16的。 
  234.                  * swr_convert 返回的是转换后每个声道(channel)的采样数 
  235.                  */  
  236.                 len2 = swr_convert(is->swr_ctx, out,  
  237.                         sizeof(is->audio_buf2) / is->audio_tgt_channels  
  238.                                 / av_get_bytes_per_sample(is->audio_tgt_fmt),  
  239.                         in, is->audio_frame->nb_samples);  
  240.                 if (len2 < 0) {  
  241.                     fprintf(stderr, "swr_convert() failed\n");  
  242.                     break;  
  243.                 }  
  244.                 if (len2  
  245.                         == sizeof(is->audio_buf2) / is->audio_tgt_channels  
  246.                                 / av_get_bytes_per_sample(is->audio_tgt_fmt)) {  
  247.                     fprintf(stderr,  
  248.                             "warning: audio buffer is probably too small\n");  
  249.                     swr_init(is->swr_ctx);  
  250.                 }  
  251.                 is->audio_buf = is->audio_buf2;  
  252.   
  253.                 //每声道采样数 x 声道数 x 每个采样字节数  
  254.                 resampled_data_size = len2 * is->audio_tgt_channels  
  255.                         * av_get_bytes_per_sample(is->audio_tgt_fmt);  
  256.             } else {  
  257.                 resampled_data_size = decoded_data_size;  
  258.                 is->audio_buf = is->audio_frame->data[0];  
  259.             }  
  260.             // We have data, return it and come back for more later  
  261.             return resampled_data_size;  
  262.         }  
  263.   
  264.         if (pkt->data)  
  265.             av_free_packet(pkt);  
  266.         memset(pkt, 0, sizeof(*pkt));  
  267.         if (is->quit)  
  268.             return -1;  
  269.         if (packet_queue_get(&is->audioq, pkt, 1) < 0)  
  270.             return -1;  
  271.   
  272.         is->audio_pkt_data = pkt->data;  
  273.         is->audio_pkt_size = pkt->size;  
  274.     }  
  275. }  
  276.   
  277. void audio_callback(void *userdata, Uint8 *stream, int len) {  
  278.     VideoState *is = (VideoState *) userdata;  
  279.     int len1, audio_data_size;  
  280.   
  281.     while (len > 0) {  
  282.         if (is->audio_buf_index >= is->audio_buf_size) {  
  283.             audio_data_size = audio_decode_frame(is);  
  284.   
  285.             if (audio_data_size < 0) {  
  286.                 /* silence */  
  287.                 is->audio_buf_size = 1024;  
  288.                 memset(is->audio_buf, 0, is->audio_buf_size);  
  289.             } else {  
  290.                 is->audio_buf_size = audio_data_size;  
  291.             }  
  292.             is->audio_buf_index = 0;  
  293.         }  
  294.   
  295.         len1 = is->audio_buf_size - is->audio_buf_index;  
  296.         if (len1 > len) {  
  297.             len1 = len;  
  298.         }  
  299.   
  300.         memcpy(stream, (uint8_t *) is->audio_buf + is->audio_buf_index, len1);  
  301.         len -= len1;  
  302.         stream += len1;  
  303.         is->audio_buf_index += len1;  
  304.     }  
  305. }  
  306.   
  307. /** 
  308.  * 设置SDL播放声音的参数如声音采样格式,声道布局,静音值 
  309.  */  
  310. int stream_component_open(VideoState *is, int stream_index) {  
  311.     AVFormatContext *ic = is->ic;  
  312.     AVCodecContext *codecCtx;  
  313.     AVCodec *codec;  
  314.     SDL_AudioSpec wanted_spec, spec;  
  315.     int64_t wanted_channel_layout = 0;  
  316.     int wanted_nb_channels;  
  317.     const int next_nb_channels[] = { 0, 0, 1, 6, 2, 6, 4, 6 };  
  318.   
  319.     if (stream_index < 0 || stream_index >= ic->nb_streams) {  
  320.         return -1;  
  321.     }  
  322.   
  323.     codecCtx = ic->streams[stream_index]->codec;  
  324.     wanted_nb_channels = codecCtx->channels;  
  325.     if (!wanted_channel_layout  
  326.             || wanted_nb_channels  
  327.                     != av_get_channel_layout_nb_channels(  
  328.                             wanted_channel_layout)) {  
  329.         wanted_channel_layout = av_get_default_channel_layout(  
  330.                 wanted_nb_channels);  
  331.         wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;  
  332.     }  
  333.   
  334.     wanted_spec.channels = av_get_channel_layout_nb_channels(  
  335.             wanted_channel_layout);  
  336.     wanted_spec.freq = codecCtx->sample_rate;  
  337.     if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {  
  338.         fprintf(stderr, "Invalid sample rate or channel count!\n");  
  339.         return -1;  
  340.     }  
  341.     wanted_spec.format = AUDIO_S16SYS;  
  342.     wanted_spec.silence = 0;  
  343.     wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;  
  344.     wanted_spec.callback = audio_callback;  
  345.     wanted_spec.userdata = is;  
  346.   
  347.     while (SDL_OpenAudio(&wanted_spec, &spec) < 0) {  
  348.         fprintf(stderr, "SDL_OpenAudio (%d channels): %s\n",  
  349.                 wanted_spec.channels, SDL_GetError());  
  350.         wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];  
  351.         if (!wanted_spec.channels) {  
  352.             fprintf(stderr,  
  353.                     "No more channel combinations to tyu, audio open failed\n");  
  354.             return -1;  
  355.         }  
  356.         wanted_channel_layout = av_get_default_channel_layout(  
  357.                 wanted_spec.channels);  
  358.     }  
  359.   
  360.     if (spec.format != AUDIO_S16SYS) {  
  361.         fprintf(stderr, "SDL advised audio format %d is not supported!\n",  
  362.                 spec.format);  
  363.         return -1;  
  364.     }  
  365.     if (spec.channels != wanted_spec.channels) {  
  366.         wanted_channel_layout = av_get_default_channel_layout(spec.channels);  
  367.         if (!wanted_channel_layout) {  
  368.             fprintf(stderr, "SDL advised channel count %d is not supported!\n",  
  369.                     spec.channels);  
  370.             return -1;  
  371.         }  
  372.     }  
  373.   
  374.     fprintf(stderr, "%d: wanted_spec.format = %d\n", __LINE__,  
  375.             wanted_spec.format);  
  376.     fprintf(stderr, "%d: wanted_spec.samples = %d\n", __LINE__,  
  377.             wanted_spec.samples);  
  378.     fprintf(stderr, "%d: wanted_spec.channels = %d\n", __LINE__,  
  379.             wanted_spec.channels);  
  380.     fprintf(stderr, "%d: wanted_spec.freq = %d\n", __LINE__, wanted_spec.freq);  
  381.   
  382.     fprintf(stderr, "%d: spec.format = %d\n", __LINE__, spec.format);  
  383.     fprintf(stderr, "%d: spec.samples = %d\n", __LINE__, spec.samples);  
  384.     fprintf(stderr, "%d: spec.channels = %d\n", __LINE__, spec.channels);  
  385.     fprintf(stderr, "%d: spec.freq = %d\n", __LINE__, spec.freq);  
  386.   
  387.     is->audio_src_fmt = is->audio_tgt_fmt = AV_SAMPLE_FMT_S16;  
  388.     is->audio_src_freq = is->audio_tgt_freq = spec.freq;  
  389.     is->audio_src_channel_layout = is->audio_tgt_channel_layout =  
  390.             wanted_channel_layout;  
  391.     is->audio_src_channels = is->audio_tgt_channels = spec.channels;  
  392.   
  393.     codec = avcodec_find_decoder(codecCtx->codec_id);  
  394.     if (!codec || (avcodec_open2(codecCtx, codec, NULL) < 0)) {  
  395.         fprintf(stderr, "Unsupported codec!\n");  
  396.         return -1;  
  397.     }  
  398.     ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;  
  399.     switch (codecCtx->codec_type) {  
  400.     case AVMEDIA_TYPE_AUDIO:  
  401.         is->audioStream = stream_index;  
  402.         is->audio_st = ic->streams[stream_index];  
  403.         is->audio_buf_size = 0;  
  404.         is->audio_buf_index = 0;  
  405.         memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));  
  406.         packet_queue_init(&is->audioq);  
  407.         SDL_PauseAudio(0);  
  408.         break;  
  409.     default:  
  410.         break;  
  411.     }  
  412. }  
  413.   
  414. /** 
  415.  * demuxing出AVPacket 
  416.  */  
  417. static int decode_thread(void *arg) {  
  418.     VideoState *is = (VideoState *) arg;  
  419.     AVFormatContext *ic = NULL;  
  420.     AVPacket pkt1, *packet = &pkt1;  
  421.     int ret, i, audio_index = -1;  
  422.   
  423.     is->audioStream = -1;  
  424.     global_video_state = is;  
  425.     if (avformat_open_input(&ic, is->filename, NULL, NULL) != 0) {  
  426.         return -1;  
  427.     }  
  428.     is->ic = ic;  
  429.     if (avformat_find_stream_info(ic, NULL) < 0) {  
  430.         return -1;  
  431.     }  
  432.     av_dump_format(ic, 0, is->filename, 0);  
  433.     for (i = 0; i < ic->nb_streams; i++) {  
  434.         if (ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO  
  435.                 && audio_index < 0) {  
  436.             audio_index = i;  
  437.             break;  
  438.         }  
  439.     }  
  440.     if (audio_index >= 0) {  
  441.         stream_component_open(is, audio_index);  
  442.     }  
  443.     if (is->audioStream < 0) {  
  444.         fprintf(stderr, "%s: could not open codecs\n", is->filename);  
  445.         goto fail;  
  446.     }  
  447.     // main decode loop  
  448.     for (;;) {  
  449.         if (is->quit)  
  450.             break;  
  451.         if (is->audioq.size > MAX_AUDIOQ_SIZE) {  
  452.             SDL_Delay(10);  
  453.             continue;  
  454.         }  
  455.         ret = av_read_frame(is->ic, packet);  
  456.         if (ret < 0) {  
  457.             if (ret == AVERROR_EOF || url_feof(is->ic->pb)) {  
  458.                 break;  
  459.             }  
  460.             if (is->ic->pb && is->ic->pb->error) {  
  461.                 break;  
  462.             }  
  463.             continue;  
  464.         }  
  465.   
  466.         if (packet->stream_index == is->audioStream) {  
  467.             packet_queue_put(&is->audioq, packet);  
  468.         } else {  
  469.             av_free_packet(packet);  
  470.         }  
  471.     }  
  472.   
  473.     while (!is->quit) {  
  474.         SDL_Delay(100);  
  475.     }  
  476.   
  477.     fail: {  
  478.         SDL_Event event;  
  479.         event.type = FF_QUIT_EVENT;  
  480.         event.user.data1 = is;  
  481.         SDL_PushEvent(&event);  
  482.     }  
  483.   
  484.     return 0;  
  485. }  
  486.   
  487. int main(int argc, char *argv[]) {  
  488.     SDL_Event event;  
  489.     VideoState *is;  
  490.   
  491.     is = (VideoState *) av_mallocz(sizeof(VideoState));  
  492.   
  493.     if (argc < 2) {  
  494.         fprintf(stderr, "Usage: test <file>\n");  
  495.         exit(1);  
  496.     }  
  497.   
  498.     av_register_all();  
  499.   
  500.     if (SDL_Init(SDL_INIT_AUDIO)) {  
  501.         fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());  
  502.         exit(1);  
  503.     }  
  504.   
  505.     av_strlcpy(is->filename, argv[1], sizeof(is->filename));  
  506.   
  507.     is->parse_tid = SDL_CreateThread(decode_thread, is);  
  508.     if (!is->parse_tid) {  
  509.         av_free(is);  
  510.         return -1;  
  511.     }  
  512.   
  513.     for (;;) {  
  514.         SDL_WaitEvent(&event);  
  515.         switch (event.type) {  
  516.         case FF_QUIT_EVENT:  
  517.         case SDL_QUIT:  
  518.             is->quit = 1;  
  519.             SDL_Quit();  
  520.             exit(0);  
  521.             break;  
  522.         default:  
  523.             break;  
  524.         }  
  525.     }  
  526.     return 0;  
  527. }  

FFmpeg版本逐渐更新,代码功能更加丰富和易于使用,掌握音视频基础概念结合ffmpeg就可以方便使用!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ffmpeg-5.0-1.5.7-windows-x86_64.jar 是一个用于在 Windows 平台上运行的 FFmpeg 库文件。它是一个开源的音视频处理工具,可以从多种媒体文件中提取、转码和编辑音视频流。 这个库文件是基于 FFmpeg 项目的最新版本 5.0 开发的。它支持在 Windows 64 位操作系统上运行,并提供了一系列功能强大的音视频处理方法。它可以读取和写入各种常见的音视频格式,包括 MP4、AVI、FLV、MOV 等。用户可以使用该库来提取音频或视频流,转码音视频文件,剪辑视频,添加字幕等。 要使用 ffmpeg-5.0-1.5.7-windows-x86_64.jar,首先需要在您的 Java 项目中引入该库文件。您可以将其作为依赖项添加到项目的 Classpath 中。然后,您可以通过在 Java 代码中调用相应的方法来使用 FFmpeg 功能。 例如,您可以使用 FFmpeg音频文件中提取音频流,然后对其进行编码或解码。您可以使用 FFmpeg 在视频文件中提取视频流,并进行截图或修改分辨率。您还可以使用 FFmpeg 对多个媒体文件进行合并或拆分操作。 除了提供强大的音视频处理功能外,ffmpeg-5.0-1.5.7-windows-x86_64.jar 还提供了丰富的文档和示例代码,以帮助用户更好地了解和使用该库。您可以参考官方文档和示例代码,了解每个方法的使用方法和参数说明。 总之,ffmpeg-5.0-1.5.7-windows-x86_64.jar 是一个在 Windows 平台上运行的 FFmpeg 库文件,提供了强大的音视频处理功能。用户可以使用它来处理音视频文件,实现音视频提取、转码、编辑等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值