21xrx.com
2025-04-12 04:11:35 Saturday
文章检索 我的文章 写文章
"C++代码制作简单生日快乐视频——致某某"
2023-07-13 16:05:52 深夜i     20     0
C++代码 生日快乐视频 制作 致某某 简单

作为一个程序员,你可能想通过自己的技术赠送一份特殊的生日礼物给你的亲人、朋友或者同事。这时候,一个用C++语言制作的生日快乐视频可能是不错的选择。

前置知识:

在使用C++编写制作视频程序之前,你需要具备以下基础知识:

1. C++编程基础

2. 第三方库 FFmpeg 的使用方法

3. 编辑器用法(比如Visual Studio等)

步骤:

1. 下载 FFmpeg 库。将 FFmpeg 安装之后在环境变量中配置 FFmpeg 的路径。这是使用 C++ 生成视频的前提条件。

2. 引入头文件并初始化 FFmpeg。需要安装好 FFmpeg 后,在编写代码文件时,需要引入 FFmpeg 的头文件并初始化该库。

extern "C"
  #include <libavcodec/avcodec.h>
  #include <libavformat/avformat.h>
  #include <libswscale/swscale.h>
  #include <libavutil/imgutils.h>
  #include <libavutil/timestamp.h>
int main()
{
  av_register_all();
  avcodec_register_all();
  return 0;
}

3. 初始化视频输出格式。我们需要指定视频输入格式、输出格式、编解码设定以及视频写入的文件名。

//Output AVFormatContext
AVFormatContext *outputAVFormatContext = NULL;
//目标文件名
char *dstFilename = "birthday.mp4";
// Create output AVLIterarContext
avformat_alloc_output_context2(&outputAVFormatContext, NULL, NULL, dstFilename);
// Create video AVStream
AVStream *outStream = avformat_new_stream(outputAVFormatContext, NULL);
// Set codec id as H264
outStream->codecpar->codec_id = AV_CODEC_ID_H264;
// Set codec as H264
AVCodec *avCodecOut = avcodec_find_encoder(outStream->codecpar->codec_id);
AVCodecContext *outCodecContext = avcodec_alloc_context3(avCodecOut);
avcodec_parameters_to_context(outCodecContext, outStream->codecpar);
outCodecContext->width = 1280;   //设置视频宽度
outCodecContext->height = 720;   //设置视频高度
outCodecContext->time_base.num = 1; //帧率分子
outCodecContext->time_base.den = 25;//帧率分母
// Set bit rate
outCodecContext->bit_rate = 400000;
// Open codec
avcodec_open2(outCodecContext, avCodecOut, NULL);
// Write file header
avformat_write_header(outputAVFormatContext, NULL);

4. 写入视频帧。我们可以在视频帧中添加文字、图片等元素。下面是一个添加文本的例子:

// 设置字体颜色、字体大小、位置等信息
AVFont font;
memset(&font, 0, sizeof(font));
strcpy(font.family_name, "Arial");
font.color = 0xFFFFFFFF;
font.size = 46;
font.out_line_thickness = 4;
// 添加文本
AVFrame *frame = av_frame_alloc();
AVFrame *text = NULL;
outCodecContext->time_base = (AVRational)1;
av_new_packet(&avPacket, outCodecContext->width * outCodecContext->height * 3);
memset(avPacket.data, 0, avPacket.size);
av_init_packet(&avPacket);
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
av_bprintf(&buf, "{\\fnArial\\fs%d\\bord%d\\3c&HFFFFFF&\\alpha&HFF&} %s", font.size, font.out_line_thickness, "Happy Birthday to someone!");
av_bprint_finalize(&buf, NULL);
if (av_bprint_is_complete(&buf)) {
  AVSubtitle sub;
  AVSubtitleRect **rects;
  text = av_frame_alloc();
  text->width = outCodecContext->width;
  text->height = outCodecContext->height;
  text->format = outCodecContext->pix_fmt;
  av_bprint_finalize(&buf, NULL);
  avcodec_subtitle_free(&sub);
  avcodec_subtitle_init(&sub);
  avsubtitle_free(&sub);
  av_bprint_finalize(&buf, NULL);
  avcodec_subtitle_free(&sub);
  avcodec_subtitle_init(&sub);
  memset(&sub, 0, sizeof(sub));
  sub.format = 0;
  sub.pts = frame->pkt_pts;
  sub.num_rects = 1;
  sub.rects = &sub_rect;
  memset(&sub_rect, 0, sizeof(sub_rect));
  sub_rect.type = SUBTITLE_ASS;
  av_bprintf(&sub_rect.text, "{\\fnArial\\fs%d\\bord%d\\3c&HFFFFFF&\\alpha&HFF&} %s", font.size, font.out_line_thickness, "Happy Birthday to someone!");
  avsubtitle_free(&sub);
  if (!outCodecContext->subtitle_header) {
    avcodec_set_subtitle_header(outCodecContext, &header, 0);
  }
  sub_rect.ass += strlen(sub_rect.ass);
  verts = sub_rect.ass + vsprintf(sub_rect.ass, "{\\pos(%d,%d)}", outCodecContext->width / 2 - 250, outCodecContext->height / 2);
  avcodec_decode_subtitle2(outCodecContext, &sub, &got_sub_packet, &avPacket);
  sub_rect.ass[0] = '\0';
  av_packet_unref(&avPacket);
}
av_packet_unref(&avPacket);

5. 写入帧到文件。

//write frame to file
bool isWriteComplete = false;
for (int i = 0; i < 180; i++) {
  AVPacket pkt = { 0 };
  av_init_packet(&pkt);
  pkt.data = NULL;
  pkt.size = 0;
  AVFrame *tmp_video_frame = av_frame_alloc();
  av_image_alloc(tmp_video_frame->data, tmp_video_frame->linesize, outCodecContext->width, outCodecContext->height, outCodecContext->pix_fmt, 1);
  avcodec_send_frame(outCodecContext, text);
  while (avcodec_receive_packet(outCodecContext, &pkt) == 0) {
    pkt.stream_index = outStream->index;
    av_interleaved_write_frame(outputAVFormatContext, &pkt);
    av_packet_unref(&pkt);
  }
  av_packet_unref(&pkt);
}

6. 释放资源。最后,我们需要释放申请的内存资源。

av_frame_free(&text);
avcodec_free_context(&outCodecContext);
av_write_trailer(outputAVFormatContext);
avio_closep(&outputAVFormatContext->pb);
avformat_free_context(outputAVFormatContext);

为了让这个生日快乐视频更符合我们的需要,我们可以添加更多有趣的元素。最终,我们就可以制作出一份特别、独一无二的生日礼物来,送给我们的亲人、朋友、同事们。

  
  

评论区