天天看點

Ffmpeg 實作檔案切割

 檔案切割是一項很常見的基本功能,通過Ffmpeg可以很容易實作這項功能。

  首先介紹下基本原理,檔案切割說白了就過濾掉檔案的部分音視訊包,按照什麼規則過濾呢?

答案是時間戳。檔案中每個視訊及音頻包都有時間戳用來辨別在哪個時間點該包被播放。當我們有過濾需求,

比如需要過濾掉視訊檔案的第3分鐘到5分鐘的視訊,首先我們需要計算第三分鐘及第五分鐘的音視訊包時間

戳區間,然後周遊視訊檔案中所有音視訊包時間戳,不再查找區間的音視訊包直接丢棄,最後将後半段音視訊包

時間戳一緻前移即可。

    基于Ffmpeg的開發流程如下圖所示:

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

如需交流,可以加QQ群1038388075,766718184,或者QQ:350197870

視訊下載下傳位址:http://www.chungen90.com/?news_33/

 Demo下載下傳位址: http://www.chungen90.com/?news_34