📜  使用 ffmpeg 将 mpg mp4 转换为 gif - C 编程语言(1)

📅  最后修改于: 2023-12-03 14:49:39.355000             🧑  作者: Mango

使用 ffmpeg 将 mpg mp4 转换为 gif

如果你需要将视频转换为 gif,可以使用 ffmpeg 命令行工具来完成。 转换 mpg 和 mp4 文件为 gif 文件的命令行如下:

ffmpeg -i input.mpg output.gif
ffmpeg -i input.mp4 output.gif

其中,input.mpginput.mp4 是你想要转换的视频文件名,output.gif 是生成的 gif 文件名。

如果你需要在命令行界面中跟踪转换进度,可以添加 -progress 参数。

ffmpeg -progress pipe:1 -i input.mp4 output.gif

这个命令会在标准输出(stdout)中输出转换进度信息。

如果你想要在 C 语言程序中使用 ffmpeg,你需要使用相关的 C 库和头文件。可以使用 libavcodec,libavformat,libavutil 和 libswscale 库完成视频编解码和格式转换。需要手动编译和安装这些库和头文件。

以下是在 C 语言程序中使用 ffmpeg 将 mpg 或 mp4 转换为 gif 的示例代码:

#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>

int main(int argc, char **argv)
{
    AVFormatContext *input_ctx = NULL;
    AVStream *video_stream = NULL;
    AVCodecParameters *codec_params = NULL;
    AVCodec *codec = NULL;
    AVPacket *packet = NULL;
    AVFrame *frame = NULL;
    int ret, stream_index, frame_count;
    struct SwsContext *sws_ctx = NULL;
    uint8_t *buffer = NULL;

    if (argc != 3) {
        printf("Usage: %s <input.mpg/mp4> <output.gif>\n", argv[0]);
        return 0;
    }

    av_register_all();
    avformat_open_input(&input_ctx, argv[1], NULL, NULL);
    avformat_find_stream_info(input_ctx, NULL);
    av_dump_format(input_ctx, 0, argv[1], 0);

    for (int i = 0; i < input_ctx->nb_streams; i++) {
        if (input_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream = input_ctx->streams[i];
            codec_params = video_stream->codecpar;
            codec = avcodec_find_decoder(codec_params->codec_id);
            break;
        }
    }

    AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
    avcodec_parameters_to_context(codec_ctx, codec_params);
    avcodec_open2(codec_ctx, codec, NULL);

    AVPixelFormat pix_fmt = AV_PIX_FMT_RGB24;
    sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
                             codec_ctx->width, codec_ctx->height, pix_fmt,
                             SWS_BILINEAR,
                             NULL, NULL, NULL);

    AVFormatContext *output_ctx = NULL;
    avformat_alloc_output_context2(&output_ctx, NULL, NULL, argv[2]);
    AVStream *out_stream = avformat_new_stream(output_ctx, NULL);
    avcodec_parameters_copy(out_stream->codecpar, codec_params);
    out_stream->codecpar->format = pix_fmt;
    avio_open(&output_ctx->pb, argv[2], AVIO_FLAG_WRITE);
    avformat_write_header(output_ctx, NULL);

    frame_count = 0;
    while (av_read_frame(input_ctx, &packet) >= 0) {
        if (packet && packet->stream_index == video_stream->index) {
            frame = av_frame_alloc();
            ret = avcodec_send_packet(codec_ctx, packet);
            if (ret < 0) {
                printf("Error decoding packet: %s\n", av_err2str(ret));
                return 1;
            }

            ret = avcodec_receive_frame(codec_ctx, frame);
            if (ret < 0) {
                printf("Error receiving frame: %s\n", av_err2str(ret));
                return 1;
            }

            if (frame) {
                AVFrame *output_frame = av_frame_alloc();
                output_frame->width = codec_params->width;
                output_frame->height = codec_params->height;
                output_frame->format = pix_fmt;
                av_frame_get_buffer(output_frame, 32);
                buffer = av_malloc(av_image_get_buffer_size(pix_fmt,
                                                            codec_ctx->width, codec_ctx->height, 1));
                av_image_fill_arrays(output_frame->data, output_frame->linesize,
                                      buffer, pix_fmt, codec_ctx->width, codec_ctx->height, 1);
                sws_scale(sws_ctx, frame->data, frame->linesize, 0,
                          codec_ctx->height, output_frame->data, output_frame->linesize);

                output_frame->pts = frame_count;
                avcodec_send_frame(codec_ctx, output_frame);

                AVPacket pkt = { 0 };
                av_init_packet(&pkt);
                pkt.data = NULL;
                pkt.size = 0;
                ret = avcodec_receive_packet(codec_ctx, &pkt);
                if (ret < 0) {
                    printf("Error receiving packet: %s\n", av_err2str(ret));
                    return 1;
                }

                av_interleaved_write_frame(output_ctx, &pkt);
                av_packet_unref(&pkt);
                av_frame_free(&output_frame);
                av_free(buffer);
            }

            av_frame_free(&frame);
            frame_count++;
        }

        av_packet_unref(&packet);
    }

    av_write_trailer(output_ctx);
    avcodec_free_context(&codec_ctx);
    avformat_close_input(&input_ctx);

    return 0;
}

这个示例代码假设你已经安装了 ffmpeg 库和头文件,并且已经链接到这些库。编译:

gcc -o myconverter myconverter.c -lavcodec -lavformat -lavutil -lswscale

然后运行:

./myconverter input.mp4 output.gif

这个程序会自动打开输入文件,解码视频流,将它们转换为 RGB24 格式,并编码为 GIF,最后输出到输出文件。