21xrx.com
2025-03-02 19:53:35 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编码器,并根据需要配置编码器参数。接下来,我们创建新的视频流,并将编码器参数复制到视频流的编码器上下文中。然后,我们打开输出文件并写入文件头。

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

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

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

  
  

评论区