文件切割是一项很常见的基本功能,通过Ffmpeg可以很容易实现这项功能。
首先介绍下基本原理,文件切割说白了就过滤掉文件的部分音视频包,按照什么规则过滤呢?
答案是时间戳。文件中每个视频及音频包都有时间戳用来标识在哪个时间点该包被播放。当我们有过滤需求,
比如需要过滤掉视频文件的第3分钟到5分钟的视频,首先我们需要计算第三分钟及第五分钟的音视频包时间
戳区间,然后遍历视频文件中所有音视频包时间戳,不再查找区间的音视频包直接丢弃,最后将后半段音视频包
时间戳一致前移即可。
基于Ffmpeg的开发流程如下图所示:
图1 视频文件切割流程图
下面介绍代码:
一. 打开视频文件获取音视频流信息
int OpenInput(string inputUrl) { inputContext = avformat_alloc_context(); lastReadPacktTime = av_gettime(); inputContext->interrupt_callback.callback = interrupt_cb; int ret = avformat_open_input(&inputContext, inputUrl.c_str(), nullptr,nullptr); if(ret < 0) { av_log(NULL, AV_LOG_ERROR, "Input file open input failed\n"); return ret; } ret = avformat_find_stream_info(inputContext,nullptr); if(ret < 0) { av_log(NULL, AV_LOG_ERROR, "Find input file stream inform failed\n"); } else { av_log(NULL, AV_LOG_FATAL, "Open input file %s success\n",inputUrl.c_str()); } return ret; }
二. 计算过滤区间
//第20S开始,去掉8S int startPacketNum = 500; int discardtPacketNum = 200;
三 遍历过滤
while(true) { auto packet = ReadPacketFromSource(); if(packet) { packetCount++; if(packetCount <= 500 || packetCount >= 700) { if(packetCount >= 700) { if(packet->pts - lastPacketPts > 120) { lastPts = lastPacketPts ; } else { auto diff = packet->pts - lastPacketPts; lastPts += diff; } } lastPacketPts = packet->pts; if(lastPts != AV_NOPTS_VALUE) { packet->pts = packet->dts = lastPts; } ret = WritePacket(packet); } } else { break; } }
完整代码下载地址:http://pan.baidu.com/s/1o8Lkozw
视频地址:http://pan.baidu.com/s/1jH4dYN8
如需交流 请加群127903734
时间: 2024-11-05 15:50:43