利用ffmpeg读取视频时长

百度了一下午,查找怎么用ffmpeg来获取视频时长,各种报错,各种不好使,心里窝火,翻墙google了一下,2分钟解决了,实在忍不住吐槽一下。下面是代码,很简单的几行代码:

package dealwithVideo;
import java.io.File;  
import java.util.ArrayList;  
import java.util.List;  
import java.util.Scanner;
import java.util.regex.Pattern;


public class ConvertVideo {  


// private final static String PATH = "F:\\ffmpeg\\1.mp4";  
//处理视频
public void dealVideo(String wholePath,String filename) {  
String videoPath = wholePath+filename;//视频路径+视频名称
if (!checkfile(videoPath)) {  //检查视频是否存在
System.out.println(videoPath + " is not file");  
return;  

if (process(wholePath,filename)) {  
System.out.println("截图完成");  
}  
}  
//检查视频是否存在
private static boolean checkfile(String path) {  
File file = new File(path);  
if (!file.isFile()) {  
return false;  
}  
return true;  
}  
//转码并截图
private static boolean process(String wholePath,String filename) {
int type = checkContentType(filename); //查看视频类型
if(type==0){//如果不是flv,则转码为flv并获取缩略图
return processFLV(wholePath,filename);// 将其他格式转为flv 
}
else{
return getPic(wholePath,filename);//如果是flv格式则直接获取缩略图
}

}  
//查看视频类型 type=0为其他类型,9为flv
private static int checkContentType(String filename) {  
String type = filename.substring(filename.length()-3,filename.length());
System.out.println(type+"------------------------");
// ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  
if (type.equals("avi")) {  
return 0;  
} else if (type.equals("mpg")) {  
return 0;  
} else if (type.equals("wmv")) {  
return 0;  
} else if (type.equals("3gp")) {  
return 0;  
} else if (type.equals("mov")) {  
return 0;  
} else if (type.equals("mp4")) {  
return 0;  
} else if (type.equals("asf")) {  
return 0;  
} else if (type.equals("asx")) {  
return 0;  
}   
return 9;  
}




private static boolean getPic(String wholePath,String filename){
String filenameBef = filename.substring(0, filename.length()-4);
//截取缩略图
List<String> commend1 = new ArrayList<String>();  
commend1.add("F:\\ffmpeg\\ffmpeg.exe");  
commend1.add("-i");  
commend1.add(wholePath+filename);  
commend1.add("-y");
// commend1.add("-f");  
commend1.add("image2");  
commend1.add("-ss");  
commend1.add("8");  
commend1.add("-s");  
commend1.add("600x500");  
commend1.add("f:\\ffmpeg\\"+filenameBef+".jpg");  
System.out.println(commend1);

try {  
Runtime runtime = Runtime.getRuntime();  
       Process proce = null;
String ffmpegStr = "F:\\ffmpeg\\ffmpeg.exe -i "+wholePath+filename+"  -f image2 " +
"-ss  5 -s 600*500 " +
  "f:\\ffmpeg\\"+filenameBef+".jpg";
proce = runtime.exec(ffmpegStr);
// ProcessBuilder builder1 = new ProcessBuilder(commend1);  
// builder1.command(commend1);  
// builder1.start();  
// System.out.println(ffmpegStr);
//获取视频总时长
Scanner sc = new Scanner(proce.getErrorStream());


       // Find duration
       Pattern durPattern = Pattern.compile("(?<=Duration: )[^,]*");
       String dur = sc.findWithinHorizon(durPattern, 0);
       if (dur == null)
         throw new RuntimeException("Could not parse duration.");
       String[] hms = dur.split(":");
       double totalSecs = Integer.parseInt(hms[0]) * 3600
                        + Integer.parseInt(hms[1]) *   60
                        + Double.parseDouble(hms[2]);
       System.out.println("Total duration: " + totalSecs + " seconds.");


return true;  
} catch (Exception e) {  
e.printStackTrace();  
return false;  
}  

}


// ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)  
private static boolean processFLV(String wholePath,String filename) {  


if (!checkfile(wholePath+filename)) {  
System.out.println(wholePath+filename+ " is not file");  
return false;  
}  
String filenameBef = filename.substring(0, filename.length()-4);
// 文件命名  
// Calendar c = Calendar.getInstance();  
// String savename = String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000);  
//转化视频
List<String> commend = new ArrayList<String>();  
commend.add("F:\\ffmpeg\\ffmpeg.exe");  
commend.add("-i");  
commend.add(wholePath+filename);  
commend.add("-ab");  
commend.add("56");  
commend.add("-ar");  
commend.add("22050");  
commend.add("-qscale");  
commend.add("8");  
commend.add("-r");  
commend.add("15");  
commend.add("-s");  
commend.add("600x500");  
commend.add("f:\\ffmpeg\\"+filenameBef+".flv"); 
try {  
Runtime runtime = Runtime.getRuntime();  
            Process proce = null;  
            String cmd = "";  
            String cut = "     f:\\ffmpeg\\ffmpeg.exe   -i   "  
                    +   wholePath+filename
                    + "      -f   image2   -ss   5   -s   600x480   f:\\ffmpeg\\"  
                    + filenameBef+".jpg";  
            String cutCmd = cmd + cut;  
            proce = runtime.exec(cutCmd);  
            ProcessBuilder builder = new ProcessBuilder(commend);  
             builder.command(commend);  
            builder.start();  
return true;  
} catch (Exception e) {  
e.printStackTrace();  
return false;  
}  

}  
}  

在C++中,你可以通过FFmpeg库来处理MP4视频并更改其时长FFmpeg是一个功能强大的多媒体框架,包含了编码、解码、流处理等众多工具。以下是使用FFmpeg C++接口(如`libavformat`和`libavcodec`)来缩短MP4视频时长的基本步骤: 1. **安装FFmpeg**:首先确保你已经安装了FFmpeg,并且它的包含头文件和库路径添加到了你的C++项目的构建环境中。 2. **链接FFmpeg库**:在你的C++项目中,需要链接到`libavformat`和`libavcodec`库。 3. **创建AVFormatContext结构体**:这是FFmpeg的核心结构,用于表示媒体文件或流。 ```cpp #include <libavformat/avformat.h> // 其他必要的FFmpeg头文件 AVFormatContext* pFormatCtx = NULL; ``` 4. **打开输入文件**: 使用`avformat_open_input()`函数打开MP4文件。 ```cpp if (!avformat_open_input(&pFormatCtx, "input.mp4", NULL, NULL)) { // 处理错误 } ``` 5. **查找并注册编解码器**: 找到视频和音频编解码器,以便后续操作。 ```cpp av_register_all(); ``` 6. **解析输入格式**: 通过`avformat_find_stream_info()`解析输入文件的元数据。 ```cpp if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { // 处理错误 } ``` 7. **获取视频流**: 根据索引找到视频流,并保存其指针。 ```cpp AVCodecContext* videoCodecCtx = pFormatCtx->streams[videoStreamIndex]->codec; ``` 8. **设置新的时长**: 创建一个新的时间戳列表,表示新时长。 ```cpp int newDuration = oldDuration * 新的比例; // 新的时长(秒) AVRational timeBase = {1, AV_TIME_BASE}; AVTime duration = av_rescale_q(newDuration, &timeBase, videoCodecCtx->time_base); ``` 9. **截取视频数据**: 使用`av_interleaved_write_frame()`从原始帧缓存中截取指定时长的数据。 ```cpp while (av_read_frame(pFormatCtx, &pkt) >= 0) { if (pkt.stream_index == videoStreamIndex) { int64_t startTs = pkt.dts + duration.num / duration.den; int64_t endTs = startTs + duration.num / duration.den; // 截取数据... } av_free_packet(&pkt); } // 当读取完成后关闭输入文件 avformat_close_input(&pFormatCtx); ``` 10. **输出到新的MP4文件**: 如果你想保存修改后的视频,需要创建一个新的输出文件,然后将截取的数据写入其中,最后关闭输出文件。 注意:这只是一个基本的示例,实际操作中可能还需要处理错误检查、编码格式转换等问题。完整的C++代码通常会封装在循环或回调函数中,以处理更复杂的流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值