使用FFmpeg进行视频解析上传视频数据
package com.greathiit.videoupload.ffmpeg;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class VideoFFmpeg {
public static void main(String[] args) {
String path="E:\\视频批量上传项目\\视频";
String timeLength = getVideoTime("E:\\视频批量上传项目\\视频\\aa.mp4","D:\\learn\\FFmpeg\\ffmpeg-N-102841-g041267b558-win64-lgpl-shared\\bin\\ffmpeg.exe");
if(timeLength.length()>0){//字符串截取
timeLength =timeLength.substring(0,timeLength.indexOf("."));
}
System.out.println("视频时长:"+timeLength);
traverseFolder1(path);
}
/**
*获取视频时间
* @param video_path 视频路径
* @param ffmpeg_path ffmpeg安装路径
* @return
*/
public static String getVideoTime(String video_path, String ffmpeg_path) {
List<String> commands = new java.util.ArrayList<String>();
commands.add(ffmpeg_path);
commands.add("-i");
commands.add(video_path);
System.out.println("命令行:"+ffmpeg_path+" -i "+video_path);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commands);
final Process p = builder.start();
//从输入流中读取视频信息
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
//从视频信息中解析时长
String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
Pattern pattern = Pattern.compile(regexDuration);
Matcher m = pattern.matcher(sb.toString());
if (m.find()) {
System.out.println(video_path+",视频时长:"+m.group(1)+", 开始时间:"+m.group(2)+",比特率:"+m.group(3)+"kb/s");
return m.group(1);
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static void traverseFolder1(String path) {
int fileNum = 0, folderNum = 0;
File file = new File(path);
if (file.exists()) {
LinkedList<File> list = new LinkedList<File>();
File[] files = file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
System.out.println("文件夹:" + file2.getAbsolutePath());
list.add(file2);
folderNum++;
} else {
System.out.println("文件:" + file2.getAbsolutePath());
fileNum++;
}
}
File temp_file;
while (!list.isEmpty()) {
temp_file = list.removeFirst();
files = temp_file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
System.out.println("文件夹:" + file2.getAbsolutePath());
list.add(file2);
folderNum++;
} else {
System.out.println("文件:" + file2.getAbsolutePath());
fileNum++;
}
}
}
} else {
System.out.println("文件不存在!");
}
System.out.println("文件夹共有:" + folderNum + ",文件共有:" + fileNum);
}
}
使用ffmpeg来获取文件的时长
https://www.cnblogs.com/firstdream/p/7676732.html : 遍历文件夹中的目录和文件
https://www.jb51.net/article/122711.htm :文件名称修改
遇到问题: 在视频修改的时候由于遍历文件目录和文件名称的时候A层目录修改了到遍历A下一层目录或者文件的时候由于保存在List集合中的绝对路径并没有发生变化就会出现文件找不到的问题。例如:
第一次修改的目录:F:\BaiduNetdiskDownload\mksz355 - 编程必备基础 计算机组成原理+操作系统+计算机网络(更多IT教程 微信352852792)==》F:\BaiduNetdiskDownload\mksz355 - 编程必备基础 计算机组成原理+操作系统+计算机网络
第遍历下一层目录:F:\BaiduNetdiskDownload\mksz355 - 编程必备基础 计算机组成原理+操作系统+计算机网络**(更多IT教程 微信352852792)**\第1章 编程必备基础:计算机组成原理、操作系统、计算机网络(更多IT教程 微信352852792) 此时加黑部分文字已经被第一次修改这时如果执行文件修改就会出现文件找不到的异常
解决办法: 使用回调函数当第一次进行修改后跳出循环重新遍历保存到List集合中如果上一次没有做修改则继续循环
具体逻辑代码如下:
package com.greathiit.videoupload.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.greathiit.videoupload.entity.Course;
import com.greathiit.videoupload.entity.Lesson;
import com.greathiit.videoupload.entity.Section;
import com.greathiit.videoupload.mapper.CourseMapper;
import com.greathiit.videoupload.service.ICourseService;
import com.greathiit.videoupload.service.ILessonService;
import com.greathiit.videoupload.service.ISectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* <p>
* 服务实现类
* </p>
*
* @author wtong
* @since 2022-04-13
*/
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
private String NO="no";
@Autowired
private ILessonService lessonService;
@Autowired
private ISectionService statisticsService;
@Override
public void saveCourse(String path) {
// String timeLength = getVideoTime("E:\\视频批量上传项目\\视频\\aa.mp4","D:\\learn\\FFmpeg\\ffmpeg-N-102841-g041267b558-win64-lgpl-shared\\bin\\ffmpeg.exe");
// if(timeLength.length()>0){//字符串截取
// timeLength =timeLength.substring(0,timeLength.indexOf("."));
// }
// System.out.println("视频时长:"+timeLength);
traverseFolder1(path);
}
private void dataEntry(List<String> stringList) {
// System.out.println(stringList.get(4));
System.out.println(stringList);
Course course = new Course();
course.setTitle(stringList.get(0));
course.setDescription("<p>"+stringList.get(0)+"<br>></p>");
course.setLanguage("chinese");
course.setCategoryId(4);
course.setSubCategoryId(3);
course.setSection("[]");
course.setRequirements("[]");
course.setLevel("beginner");
course.setUserId(85);
course.setDateAdded(1623999600);
course.setIsAdmin(0);
course.setStatus("active");
course.setMetaKeywords(stringList.get(0));
course.setIsFreeCourse(1);
// //保存章节
QueryWrapper<Course> queryWrapper=new QueryWrapper<>();
queryWrapper.lambda().eq(Course::getTitle,course.getTitle());
// this.saveOrUpdate(course,queryWrapper);
Section section=new Section();
section.setTitle(stringList.get(1));
section.setCourseId(417);
try {
section.setOrder(Integer.parseInt(section.getTitle().substring(1,3)));
}catch (NumberFormatException e){
section.setOrder(Integer.parseInt(section.getTitle().substring(1,2)));
}
QueryWrapper<Section> sectionQueryWrapper=new QueryWrapper<>();
sectionQueryWrapper.lambda().eq(Section::getTitle,section.getTitle());
// statisticsService.saveOrUpdate(section,sectionQueryWrapper);
Lesson lesson = new Lesson();
lesson.setTitle(stringList.get(2));
lesson.setDuration(stringList.get(3));
lesson.setVideoUrl(stringList.get(6).replace("F:\\BaiduNetdiskDownload",""));
lesson.setVideoUrlForMobileApplication(stringList.get(6).replace("F:\\BaiduNetdiskDownload",""));
Long dateAdded = System.currentTimeMillis();
// String s = dateAdded.toString();
// Integer sp = Integer.parseInt(s);
// lesson.setDateAdded(sp);
lesson.setLessonType("video");
lesson.setAttachmentType("url");
try {
lesson.setOrder(Integer.parseInt(lesson.getTitle().substring(2,4)));
}catch (NumberFormatException e){
lesson.setOrder(Integer.parseInt(lesson.getTitle().substring(2,3)));
}
lesson.setVideoType("Vimeo");
lesson.setVideoTypeForMobileApplication("html5");
Course one = this.getOne(queryWrapper);
lesson.setCourseId(one.getId());
Section one1 = statisticsService.getOne(sectionQueryWrapper);
lesson.setSectionId(one1.getId());
lesson.setVideoTypeForMobileApplication(stringList.get(6).replace("F:\\BaiduNetdiskDownload",""));
QueryWrapper<Lesson> queryWrapperlqueryWrap=new QueryWrapper<>();
queryWrapperlqueryWrap.lambda().eq(Lesson::getTitle,lesson.getTitle());
lessonService.saveOrUpdate(lesson,queryWrapperlqueryWrap);
System.out.println(lesson.toString());
}
// public static void main(String[] args) {
// String path="F:\\BaiduNetdiskDownload\\mksz355 - 编程必备基础 计算机组成原理+操作系统+计算机网络";
String timeLength = getVideoTime("E:\\视频批量上传项目\\视频\\aa.mp4","D:\\learn\\FFmpeg\\ffmpeg-N-102841-g041267b558-win64-lgpl-shared\\bin\\ffmpeg.exe");
if(timeLength.length()>0){//字符串截取
timeLength =timeLength.substring(0,timeLength.indexOf("."));
}
System.out.println("视频时长:"+timeLength);
// traverseFolder1(path);
//
//
// }
/**
*获取视频时间
* @param video_path 视频路径
* @param ffmpeg_path ffmpeg安装路径
* @return
*/
public String getVideoTime(String video_path, String ffmpeg_path) {
//将命令行拼接到list集合中
List<String> commands = new java.util.ArrayList<String>();
commands.add(ffmpeg_path);
commands.add("-i");
commands.add(video_path);
// System.out.println("命令行:"+ffmpeg_path+" -i "+video_path);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commands);
final Process p = builder.start();
//从输入流中读取视频信息
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
//从视频信息中解析时长
String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
Pattern pattern = Pattern.compile(regexDuration);
Matcher m = pattern.matcher(sb.toString());
if (m.find()) {
List<String > re=replace(video_path);
// System.out.println(re.toString());
System.out.println(video_path+",视频时长:"+m.group(1)+", 开始时间:"+m.group(2)+",比特率:"+m.group(3)+"kb/s" );
re.add(m.group(1));
re.add(m.group(2));
re.add(m.group(3));
re.add(video_path);
dataEntry(re);
return m.group(1);
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 字符串分割
* @param video_path 需要分割的绝对路径
* @return 返回分割好的数据列表
*/
private List<String> replace(String video_path) {
String replace = video_path.replace("F:\\BaiduNetdiskDownload\\mksz355 - ", "");
Character a=92;
String am=a.toString();
System.out.println(replace);
System.out.println("");
String[] split1 = replace.split("\\\\");
int ac=split1.length;
System.out.println(ac);
String course = split1[0];//课程名称
String chapter = split1[1];//章节
String blues = split1[2];
String[] split2 = blues.split("\\.");
blues = split2[0]; //集数
List<String> list=new ArrayList<>();
list.add(course);
list.add(chapter);
list.add(blues);
return list;
}
public void traverseFolder1(String path) {
int fileNum = 0, folderNum = 0;
File file = new File(path);
LinkedList<File> rnameList = new LinkedList<>();
if (file.exists()) {
LinkedList<File> list = new LinkedList<File>();
File[] files = file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
// System.out.println("文件夹:" + file2.getAbsolutePath());
list.add(file2);
rnameList.add(file2);
folderNum++;
} else {
// System.out.println("文件1:" + file2.getAbsolutePath());
rnameList.add(file2);
fileNum++;
}
}
File temp_file;
while (!list.isEmpty()) {
temp_file = list.removeFirst();
files = temp_file.listFiles();
for (File file2 : files) {
rnameList.add(file2);
if (file2.isDirectory()) {
// System.out.println("文件夹:" + file2.getAbsolutePath());
list.add(file2);
folderNum++;
} else {
// System.out.println("文件2:" + file2.getAbsolutePath());
fileNum++;
}
}
}
} else {
System.out.println("文件不存在!");
}
System.out.println("文件夹共有:" + folderNum + ",文件共有:" + fileNum);
int msize = 0;
for (File file1 : rnameList) {
String absolutePath = file1.getAbsolutePath();
String timeLength = getVideoTime(absolutePath,"D:\\learn\\FFmpeg\\ffmpeg-N-102841-g041267b558-win64-lgpl-shared\\bin\\ffmpeg.exe");
if(timeLength.length()>0){//字符串截取
timeLength =timeLength.substring(0,timeLength.indexOf("."));
}
// System.out.println("视频时长:"+timeLength+"path"+absolutePath);
// String result = rName(file1);
// if(!result.equals(NO)){
// traverseFolder1( path);
// break;
//
// }
msize++;
}
}
private String rName(File file2) {
String absolutePath = file2.getAbsolutePath();
String[] split = absolutePath.split(File.pathSeparator);
String s = split[split.length - 1];
String replace = s.replace("(更多IT教程 微信352852792)", "");
if(s.equals(replace)){
return NO;
}
File file1 = new File(replace);
if(file2.renameTo(file1)){
System.out.println("修改成功");
}else {
System.out.println("修改失败");
}
return replace;
}
}
进行视频批量处理因为视频缺少h264加入h264生成新的文件后缀多.mp4
function recursive_list_dir(){
for file_or_dir in `ls $1`
do
if [ -d $1"/"$file_or_dir ]
then
recursive_list_dir $1"/"$file_or_dir
else
file=$1"/"$file_or_dir
if [ "${file##*.}" = "mp4" ]
then
aa="${file##*/}"
if [ "${aa##*.}" = "mp4.mp4" ]
then
echo "ii"
else
docker run -it --name app_ffmpeg -v $PWD:/tmp/workdir jrottenberg/ffmpeg -i ${file:3} -vcodec h264 ${file:3}.mp4
docker rm -f app_ffmpeg
fi
fi
fi
done
}
recursive_list_dir $1