21xrx.com
2024-12-22 11:20:25 Sunday
登录
文章检索 我的文章 写文章
使用FFmpeg录制MP4视频的代码
2023-11-22 08:55:27 深夜i     --     --
FFmpeg 录制 MP4视频 代码 编程

FFmpeg是一个开源的多媒体框架,可以用于处理视频、音频等多媒体文件。它提供了丰富的功能和强大的性能,因此被广泛应用于各种多媒体处理任务中。本文将介绍使用FFmpeg录制MP4视频的代码示例。

在开始使用FFmpeg进行视频录制之前,我们首先需要安装FFmpeg工具。具体安装方法可以参考FFmpeg官方文档或者其他相关资料。安装完成后,我们可以通过以下代码示例实现视频录制:


#include <stdio.h>

#include <stdlib.h>

#include <stdint.h>

extern "C"

#include <libavcodec/avcodec.h>

#include <libavutil/opt.h>

#include <libavutil/imgutils.h>

int main(int argc, char *argv[]) {

  int ret;

  AVFormatContext *formatContext = NULL;

  AVCodecContext *codecContext = NULL;

  AVOutputFormat *outputFormat = NULL;

  AVStream *videoStream = NULL;

  AVCodec *codec = NULL;

  AVFrame *frame = NULL;

  AVPacket packet;

  const char *filename = "output.mp4";

  int width = 640;

  int height = 480;

  int fps = 25;

  // 初始化FFmpeg库

  av_register_all();

  // 创建输出格式上下文

  ret = avformat_alloc_output_context2(&formatContext, NULL, NULL, filename);

  if (ret < 0) {

    fprintf(stderr, "Error creating format context\n");

    exit(1);

  }

  // 查找H.264编码器

  codec = avcodec_find_encoder(AV_CODEC_ID_H264);

  if (!codec) {

    fprintf(stderr, "Codec not found\n");

    exit(1);

  }

  // 创建编码器上下文

  codecContext = avcodec_alloc_context3(codec);

  if (!codecContext) {

    fprintf(stderr, "Could not allocate video codec context\n");

    exit(1);

  }

  // 配置编码器参数

  codecContext->bit_rate = 1000000;

  codecContext->width = width;

  codecContext->height = height;

  codecContext->time_base = (AVRational)1;

  codecContext->framerate = (AVRational)fps;

  codecContext->gop_size = 10;

  codecContext->max_b_frames = 1;

  codecContext->pix_fmt = AV_PIX_FMT_YUV420P;

  // 打开编码器

  ret = avcodec_open2(codecContext, codec, NULL);

  if (ret < 0) {

    fprintf(stderr, "Could not open codec\n");

    exit(1);

  }

  // 创建新的视频流

  videoStream = avformat_new_stream(formatContext, codec);

  if (!videoStream) {

    fprintf(stderr, "Could not create video stream\n");

    exit(1);

  }

  // 将编码器参数复制到视频流的编码器上下文中

  ret = avcodec_parameters_from_context(videoStream->codecpar, codecContext);

  if (ret < 0) {

    fprintf(stderr, "Could not copy codec parameters\n");

    exit(1);

  }

  // 打开输出文件

  ret = avio_open(&formatContext->pb, filename, AVIO_FLAG_WRITE);

  if (ret < 0) {

    fprintf(stderr, "Could not open output file\n");

    exit(1);

  }

  // 写入文件头

  ret = avformat_write_header(formatContext, NULL);

  if (ret < 0) {

    fprintf(stderr, "Error writing header\n");

    exit(1);

  }

  // 分配帧内存

  frame = av_frame_alloc();

  if (!frame) {

    fprintf(stderr, "Could not allocate video frame\n");

    exit(1);

  }

  // 设置帧参数

  frame->format = codecContext->pix_fmt;

  frame->width = codecContext->width;

  frame->height = codecContext->height;

  // 分配帧数据缓冲区

  ret = av_frame_get_buffer(frame, 0);

  if (ret < 0) {

    fprintf(stderr, "Could not allocate frame data\n");

    exit(1);

  }

  // 循环录制帧

  for (int i = 0; i < 100; i++) {

    // 生成虚拟帧数据(这里使用黑色帧作为示例)

    for (int y = 0; y < height; y++) {

      for (int x = 0; x < width; x++) {

        frame->data[0][y * frame->linesize[0] + x] = 0;   // Y分量

        frame->data[1][y/2 * frame->linesize[1] + x/2] = 128;  // U分量

        frame->data[2][y/2 * frame->linesize[2] + x/2] = 128;  // V分量

      }

    }

    // 设置帧时间戳和位置

    frame->pts = i * videoStream->time_base.den / (videoStream->time_base.num * fps);

    // 编码帧

    ret = avcodec_send_frame(codecContext, frame);

    if (ret < 0) {

      fprintf(stderr, "Error sending frame\n");

      exit(1);

    }

    while (ret >= 0) {

      ret = avcodec_receive_packet(codecContext, &packet);

      if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {

        break;

      } else if (ret < 0) {

        fprintf(stderr, "Error receiving packet\n");

        exit(1);

      }

      // 写入视频包

      packet.stream_index = videoStream->index;

      ret = av_write_frame(formatContext, &packet);

      if (ret < 0) {

        fprintf(stderr, "Error writing frame\n");

        exit(1);

      }

    }

    av_packet_unref(&packet);

  }

  // 写入文件尾

  ret = av_write_trailer(formatContext);

  if (ret < 0) {

    fprintf(stderr, "Error writing trailer\n");

    exit(1);

  }

  // 释放资源

  avformat_free_context(formatContext);

  avcodec_free_context(&codecContext);

  av_frame_free(&frame);

  return 0;

}

以上代码示例演示了如何使用FFmpeg进行MP4视频录制的过程。首先,我们初始化FFmpeg库并创建输出格式上下文。然后,我们查找并选择H.264编码器,并根据需要配置编码器参数。接下来,我们创建新的视频流,并将编码器参数复制到视频流的编码器上下文中。然后,我们打开输出文件并写入文件头。

接下来,我们通过循环录制帧数据来生成视频。在每一帧中,我们可以根据需要生成虚拟的帧数据,然后设置帧时间戳和位置。然后,我们将帧数据发送到编码器进行编码,并将编码后的视频包写入输出文件中。

最后,我们在录制完成后写入文件尾,并释放相关资源。

注意:以上代码示例只是一个简单的示例,实际应用中可能需要进行更多的参数配置和错误处理,以及添加音频录制等功能。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复