Ffmpeg 实现文件切割

文件切割是一项很常见的基本功能,通过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

Ffmpeg 实现文件切割的相关文章

java实现把一个大文件切割成N个固定大小的文件

//java实现把一个大文件切割成N个固定大小的文件 package com.johnny.test; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; public class FenGeFile { p

java下io文件切割合并功能加配置文件

package cn.stat.p1.file; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.SequenceInputStream; import java.util.ArrayList; import ja

Nginx 日志文件切割

Nginx 是一个非常轻量的 Web 服务器,体积小.性能高.速度快等诸多优点.但不足的是也存在缺点,比如其产生的访问日志文件一直就是一个,不会自动地进行切割,如果访问量很大的话,将 导致日志文件容量非常大,不便于管理.当然了,我们也不希望看到这么庞大的一个访问日志文件,那需要手动对这个文件进行切割. 在 Linux 平台上 Shell 脚本丰富,使用 Shell 脚本加 crontab 命令能非常方便地进行切割,但在 Windows 平台上就麻烦一些了,刚才弄了好长时间,就在这里记录整理一下.

JAVA学习第五十五课 — IO流(九)文件切割合成器

文件切割器 private static final int SIZE = 1024 *1024; public static void splitFile(File file) throws IOException{ //用读取流关联文件(不确定文件格式) FileInputStream fis = new FileInputStream(file);//源是一个 byte[] by = new byte[SIZE];//定义1M的缓冲区 FileOutputStream fos = null

python之文件切割保存

最近在看小甲鱼的视频,把写的文件切割代码拿出来捋捋 #-*- coding:utf-8 -*- f = open('foo.txt') man = [] #定义两个空列表 women =[] count = 1 #初始化计数器 for each_line in f: if each_line[:6] != '======': #如果文档未遇到分隔符,则切割 (role,line_spoken) = each_line.split(':',1)#遇到冒号则切割1次 if role == 'boy'

java 文件切割,为什么在关闭流的时候报错,51行

1 package java_IO.Test_1.File_Split_and_SequeceDemo; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 8 public class FileSplit { 9 10 private File file; 11 private int size;

Ajax实现大文件切割上传

Ajax大文件切割上传 2015-02-07 前面我们已经实现了Ajax的文件上传,不过会受限于服务器的允许的大小, 如果服务器并非自己的,我们就要使用Ajax大文件切割来实现上传. 首先解决Ajax跨域上传问题: 在HTML5中,ajax的跨域有了新的规则-----能否跨域取决于对应的应答. 对方服务器如果愿意接受远程过来的ajax,或某几个域名过来的ajax请求,可以在头信息header中,加入Access-Control-Allow-Origin * 在PHP中加入此信息,就可以实现跨域请

Nginx日志文件切割

Nginx 是一个非常轻量的 Web 服务器,体积小.性能高.速度快等诸多优点.但不足的是也存在缺点,比如其产生的访问日志文件一直就是一个,不会自动地进行切割,如果访问量很大的话,将 导致日志文件容量非常大,不便于管理.当然了,我们也不希望看到这么庞大的一个访问日志文件,那需要手动对这个文件进行切割. 在 Linux 平台上 Shell 脚本丰富,使用 Shell 脚本加 crontab 命令能非常方便地进行切割 日志文件切割要求 由于 Nginx 的日志都是写在一个文件当中的,因此,我们需要每

split命令:文件切割

有时候文件过大,导致不能正常使用,可以用split进行切割. 命令参数: split [选项] [要切割的文件] [输出文件名前缀] -a, --suffix-length=N  切割文件的后缀的位置,default 为2 -b, --bytes=SIZE       指定块的大小,可以指定size的单位,b表示512字节,k代表1K字节,m代表1M字节,还有G,T,P -d, --numeric-suffixes 利用数据前缀,而不是字母前缀,默认是字母前缀. -l, --lines=NUMB