21xrx.com
2024-12-22 20:52:53 Sunday
登录
文章检索 我的文章 写文章
"C++代码制作简单生日快乐视频——致某某"
2023-07-13 16:05:52 深夜i     --     --
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);

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

  
  

评论区

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