如何使用 FFmpeg C API 剪切视频 [英] How to cut video with FFmpeg C API
本文介绍了如何使用 FFmpeg C API 剪切视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
如何使用 FFmpeg C API 剪切视频?例如从 00:10:00 到 00:20:00.我需要使用哪些功能?
How can I cut video with FFmpeg C API? From 00:10:00 to 00:20:00 for example. What functions I need to use?
我使用此功能转换视频:
I convert video using this function:
int convert(char *file) {
AVFrame *frame;
AVPacket inPacket, outPacket;
if(avio_open(&outFormatContext->pb, file, AVIO_FLAG_WRITE) < 0) {
fprintf(stderr, "convert(): cannot open out file\n");
return 0;
}
avformat_write_header(outFormatContext, NULL);
frame = avcodec_alloc_frame();
av_init_packet(&inPacket);
while(av_read_frame(inFormatContext, &inPacket) >= 0) {
if(inPacket.stream_index == inVideoStreamIndex) {
avcodec_decode_video2(inCodecContext, frame, &frameFinished, &inPacket);
if(frameFinished) {
av_init_packet(&outPacket);
avcodec_encode_video2(outCodecContext, &outPacket, frame, &outputed);
if(outputed) {
if (av_write_frame(outFormatContext, &outPacket) != 0) {
fprintf(stderr, "convert(): error while writing video frame\n");
return 0;
}
}
av_free_packet(&outPacket);
}
}
}
av_write_trailer(outFormatContext);
av_free_packet(&inPacket);
return 1;
}
推荐答案
如果您只想剪切视频,则无需重新编码视频.所以我假设你出于某种原因想要剪切和重新编码.因此,根据您的代码:
If you just wanna cut the video, you don't need to reencode the video if you want. So I am supposing you wanna cut and reencode for some reason. So, based on your code:
请注意,您必须有权访问视频 AVStream*
结构...我将其命名为 inVideoStream
.
Observe you must to have access to the video AVStream*
structure... I named it as inVideoStream
.
int convert_and_cut(char *file, float starttime, float endtime) {
AVFrame *frame;
AVPacket inPacket, outPacket;
if(avio_open(&outFormatContext->pb, file, AVIO_FLAG_WRITE) < 0) {
fprintf(stderr, "convert(): cannot open out file\n");
return 0;
}
// seek to the start time you wish.
// BEGIN
AVRational default_timebase;
default_timebase.num = 1;
default_timebase.den = AV_TIME_BASE;
// suppose you have access to the "inVideoStream" of course
int64_t starttime_int64 = av_rescale_q((int64_t)( starttime * AV_TIME_BASE ), default_timebase, inVideoStream->time_base);
int64_t endtime_int64 = av_rescale_q((int64_t)( endtime * AV_TIME_BASE ), default_timebase, inVideoStream->time_base);
if(avformat_seek_file(inFormatContext, inVideoStreamIndex, INT64_MIN, starttime_int64, INT64_MAX, 0) < 0) {
// error... do something...
return 0; // usually 0 is used for success in C, but I am following your code.
}
avcodec_flush_buffers( inVideoStream->codec );
// END
avformat_write_header(outFormatContext, NULL);
frame = avcodec_alloc_frame();
av_init_packet(&inPacket);
// you used avformat_seek_file() to seek CLOSE to the point you want... in order to give precision to your seek,
// just go on reading the packets and checking the packets PTS (presentation timestamp)
while(av_read_frame(inFormatContext, &inPacket) >= 0) {
if(inPacket.stream_index == inVideoStreamIndex) {
avcodec_decode_video2(inCodecContext, frame, &frameFinished, &inPacket);
// this line guarantees you are getting what you really want.
if(frameFinished && frame->pkt_pts >= starttime_int64 && frame->pkt_pts <= endtime_int64) {
av_init_packet(&outPacket);
avcodec_encode_video2(outCodecContext, &outPacket, frame, &outputed);
if(outputed) {
if (av_write_frame(outFormatContext, &outPacket) != 0) {
fprintf(stderr, "convert(): error while writing video frame\n");
return 0;
}
}
av_free_packet(&outPacket);
}
// exit the loop if you got the frames you want.
if(frame->pkt_pts > endtime_int64) {
break;
}
}
}
av_write_trailer(outFormatContext);
av_free_packet(&inPacket);
return 1;
}
这篇关于如何使用 FFmpeg C API 剪切视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文