ffmpeg使用及java操作

1.文档

官网: FFmpeg
官方使用文档: ffmpeg Documentation

中文简介: https://www.cnblogs.com/leisure_chn/p/10297002.html

函数及时间: ffmpeg日记1011-过滤器-语法高阶,逻辑,函数使用_ffmpeg gte(t,2)-CSDN博客

java集成ffmpeg: SpringBoot集成ffmpeg实现视频转码播放_jave-all-deps-CSDN博客 

2.命令

快速复制视频片段
ffmpeg -ss 00:00:40 -i test.mp4 -to 00:01:00 -c:v copy -c:a copy  testOutput40.mp4复制视频片段,并调整视频质量,crf一般为23,crf越大压缩越厉害,质量下降越多
ffmpeg -i test.mp4 -ss 00:30 -to 00:50 -c:v libx264 -crf 23 newTest1.mp4调整视频分辨率(调整的分辨率超过原来的,不能提升画质)
ffmpeg -i test.mp4 -vf scale=432:240 video_240p.mp4 -hide_banner
ffmpeg -i test.mp4 -vf scale=-1:240 video_240p.mp4 -hide_banner加水印(10:10水印距离左上角的像素距离)
ffmpeg -i test.mp4 -i used100.png -filter_complex "overlay=10:10" testOutputWater.mp4--保真加水印,不怎么改变视频编码及质量
ffmpeg -i test.mp4 -i used100.png -filter_complex "overlay=10:10" -c:v libx264 -c:a copy testOutputWater2.mp4--视频2秒后开始显示水印,gte(t\,2)
ffmpeg -i test.mp4 -vf "movie=used100.png[logo];[in][logo]overlay=x='if(gte(t\,2)\,0\,NAN)'" testOutputWater6.mp4--在指定时间范围(20-30秒)显示水印,between(t\,20\,30)
ffmpeg -i test.mp4 -vf "movie=used100.png[logo];[in][logo]overlay=x='if(between(t\,20\,30)\,0\,NAN)'" testOutputWater9.mp4加硬字幕
ffmpeg -i test.mp4 -vf subtitles=test.srt mp4_add_captions1.mp4

3.java代码

        maven依赖,使用集成的ffmpeg程序,缺点是打成的jar包很大,优点是不需要手动安装ffmpeg

        <!--   音视频   --><dependency><groupId>ws.schild</groupId><artifactId>jave-all-deps</artifactId><version>3.0.1</version><exclusions><!--  排除windows 32位系统      --><exclusion><groupId>ws.schild</groupId><artifactId>jave-nativebin-win32</artifactId></exclusion><!--  排除linux 32位系统      --><exclusion><groupId>ws.schild</groupId><artifactId>jave-nativebin-linux32</artifactId></exclusion><!-- 排除Mac系统--><exclusion><groupId>ws.schild</groupId><artifactId>jave-nativebin-osx64</artifactId></exclusion></exclusions></dependency>

          第二种方式,不引入集成的ffmpeg,手动在程序运行的服务器上安,优点是打成的jar包较小,关于如何手动在服务器上配置ffmpeg,请见附录2

        <!--音视频操作--><dependency><groupId>ws.schild</groupId><artifactId>jave-core</artifactId><version>3.0.1</version></dependency>

        工具类

package mis.shared.file;import lombok.extern.slf4j.Slf4j;
import ws.schild.jave.Encoder;
import ws.schild.jave.EncoderException;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.encode.VideoAttributes;
import ws.schild.jave.info.MultimediaInfo;
import ws.schild.jave.process.ProcessWrapper;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;/*** 音视频操作** @since 2024/1/22*/
@Slf4j
public class FfmpegUtil {/*** 通过本地路径获取多媒体文件信息(宽,高,时长,编码等)** @param localPath 文件路径* @return MultimediaInfo 媒体对象,包含 (宽,高,时长,编码等)*/public static MultimediaInfo GetMediaInfo(String localPath) {MultimediaInfo multimediaInfo = null;try {multimediaInfo = new MultimediaObject(new File(localPath)).getInfo();} catch (EncoderException e) {log.error("获取媒体信息异常!", e);}return multimediaInfo;}/*** 修改视频分辨率,修改分辨率超过原视频,不能提高画质* 标清SD(Standard Definition) 宽 x 高* 480p 640x480 704x480 720x480 848x480* 高清 HD(High Definition)* 720p 960x720 1280x720* 1080p 1440x1080 1920x1080* 超高清UHD(Ultra High Definition)* 4k 4096×3112 4096*2160** @param inputPath  视频来源地址* @param outputPath 输出视频地址* @param width      宽度* @param height     高度*/public static boolean ChangeScale(String inputPath, String outputPath, int width, int height) {ProcessWrapper ffmpeg = null;try {if (new File(outputPath).exists()) {log.error("目标文件已存在,outputPath:{}", outputPath);return false;}ffmpeg = new DefaultFFMPEGLocator().createExecutor();ffmpeg.addArgument("-i");ffmpeg.addArgument(inputPath);ffmpeg.addArgument("-vf");ffmpeg.addArgument("scale=" + width + ":" + height);ffmpeg.addArgument("-c:a");ffmpeg.addArgument("copy");ffmpeg.addArgument(outputPath);long start = System.currentTimeMillis();//异步执行ffmpeg.execute();//等待完成WaitFfmpegFinish(ffmpeg);log.info("花费时间:{}", System.currentTimeMillis() - start);return true;} catch (Exception e) {log.error("修改视频画质异常", e);} finally {if (ffmpeg != null) {ffmpeg.destroy();}}return false;}/*** 复制视频片段** @param inputPath  视频来源地址* @param outputPath 输出视频地址* @param startTime  开始时间,01:02:03在视频的第1小时第2分钟第3秒处* @param endTime    结束时间,格式同startTime*/public static boolean CopyVideo(String inputPath, String outputPath, String startTime, String endTime) {ProcessWrapper ffmpeg = null;try {if (new File(outputPath).exists()) {log.error("目标文件已存在,outputPath:{}", outputPath);return false;}ffmpeg = new DefaultFFMPEGLocator().createExecutor();ffmpeg.addArgument("-ss");ffmpeg.addArgument(startTime);ffmpeg.addArgument("-i");ffmpeg.addArgument(inputPath);ffmpeg.addArgument("-to");ffmpeg.addArgument(endTime);ffmpeg.addArgument("-c:v");ffmpeg.addArgument("copy");ffmpeg.addArgument("-c:a");ffmpeg.addArgument("copy");ffmpeg.addArgument(outputPath);long start = System.currentTimeMillis();//异步执行ffmpeg.execute();//等待完成WaitFfmpegFinish(ffmpeg);log.info("花费时间:{}", System.currentTimeMillis() - start);return true;} catch (Exception e) {log.error("复制视频片段异常", e);} finally {if (ffmpeg != null) {ffmpeg.destroy();}}return false;}/*** 视频格式转换为mp4*/public static boolean FormatToMp4(String localPath, String outputPath) {try {File target = new File(outputPath);if (target.exists()) {log.error("目标文件已存在,outputPath:{}", outputPath);return false;}MultimediaObject multimediaObject = new MultimediaObject(new File(localPath));EncodingAttributes attributes = new EncodingAttributes();// 设置视频的音频参数AudioAttributes audioAttributes = new AudioAttributes();attributes.setAudioAttributes(audioAttributes);// 设置视频的视频参数VideoAttributes videoAttributes = new VideoAttributes();// 设置帧率videoAttributes.setFrameRate(25);attributes.setVideoAttributes(videoAttributes);// 设置输出格式attributes.setOutputFormat("mp4");Encoder encoder = new Encoder();encoder.encode(multimediaObject, target, attributes);return true;} catch (Exception e) {log.error("视频转换异常!", e);return false;}}/*** 获取视频缩略图* 获取视频第0秒的第一帧图片*/public static boolean GetThumbnail(String localPath, String outputPath) {ProcessWrapper ffmpeg = null;try {File target = new File(outputPath);if (target.exists()) {log.error("目标文件已存在,outputPath:{}", outputPath);return false;}ffmpeg = new DefaultFFMPEGLocator().createExecutor();ffmpeg.addArgument("-i");ffmpeg.addArgument(localPath);ffmpeg.addArgument("-ss");ffmpeg.addArgument("0");ffmpeg.addArgument(outputPath);ffmpeg.execute();//等待执行完成WaitFfmpegFinish(ffmpeg);} catch (Exception e) {log.error("获取视频缩略图异常", e);return false;} finally {if (ffmpeg != null) {ffmpeg.destroy();}}return true;}/*** 等待命令执行完成*/private static void WaitFfmpegFinish(ProcessWrapper processWrapper) throws Exception {//输出执行情况不是通过inputStream,而是errorStreamtry (BufferedReader br = new BufferedReader(new InputStreamReader(processWrapper.getErrorStream()))) {String processInfo;while ((processInfo = br.readLine()) != null) {//打印执行过程log.trace(processInfo);}} catch (Exception e) {log.error("等待执行完成异常!", e);}}public static void main(String[] args) {String inputFile = "e://develop//tmp//test.mp4";String outputFile = "e://develop//tmp//testOutput14.mp4";//复制视频指定片段CopyVideo(inputFile, outputFile, "00:00:10", "00:01:00");//获取媒体信息// MultimediaInfo multimediaInfo = GetMediaInfo(inputFile);// log.info("文件信息:{}", multimediaInfo);// VideoSize videoSize = multimediaInfo.getVideo().getSize();// log.info("文件信息,宽:{},高:{}", videoSize.getWidth(), videoSize.getHeight());//修改视频画质//ChangeScale(inputFile, outputFile, 640, 480);}}

附录1

         字幕test.srt

1
00:00:20,000 --> 00:00:30,000
这是视频第20秒到30秒将显示的字幕2
00:00:50,000 --> 00:00:60,000
这是视频第50秒到60秒将显示的字幕

附录2

        关于ffmpeg在服务器上的位置,参考如下代码

  public DefaultFFMPEGLocator() {String os = System.getProperty("os.name").toLowerCase();boolean isWindows = os.contains("windows");boolean isMac = os.contains("mac");LOG.debug("Os name is <{}> isWindows: {} isMac: {}", os, isWindows, isMac);// Dir FolderFile dirFolder = new File(System.getProperty("java.io.tmpdir"), "jave/");if (!dirFolder.exists()) {LOG.debug("Creating jave temp folder to place executables in <{}>", dirFolder.getAbsolutePath());dirFolder.mkdirs();} else {LOG.debug("Jave temp folder exists in <{}>", dirFolder.getAbsolutePath());}// -----------------ffmpeg executable export on disk.-----------------------------String suffix = isWindows ? ".exe" : (isMac ? "-osx" : "");String arch = System.getProperty("os.arch");// FileFile ffmpegFile = new File(dirFolder, "ffmpeg-" + arch + "-" + Version.getVersion() + suffix);LOG.debug("Executable path: {}", ffmpegFile.getAbsolutePath());// Check the version of existing .exe fileif (ffmpegFile.exists()) {// OK, already presentLOG.debug("Executable exists in <{}>", ffmpegFile.getAbsolutePath());} else {LOG.debug("Need to copy executable to <{}>", ffmpegFile.getAbsolutePath());copyFile("ffmpeg-" + arch + suffix, ffmpegFile);}// Need a chmod?if (!isWindows) {try {Runtime.getRuntime().exec(new String[] {"/bin/chmod", "755", ffmpegFile.getAbsolutePath()});} catch (IOException e) {LOG.error("Error setting executable via chmod", e);}}// Everything seems okaypath = ffmpegFile.getAbsolutePath();if (ffmpegFile.exists()){LOG.debug("ffmpeg executable found: {}", path);}else{LOG.error("ffmpeg executable NOT found: {}", path);}}

       windows环境,打开cmd窗口,执行echo %TEMP%获取临时文件夹,打开临时文件夹,创建子文件夹jave(最终路径例子C:\Users\TN\AppData\Local\Temp\jave)

        下载ws.schild的maven对应系统jar包,并解压jave-nativebin-win64-3.0.1,找到里面的ffmpeg-amd64.exe复制到上面的目录下

         linux通过脚本获取默认目录,原理是通过编译运行FfmpegHelper.java获得

#!/bin/bashcd /tmp# download 
if [ -e "/tmp/FfmpegHelper.java" ]
thenecho "FfmpegHelper.java already exist!"
elseecho "FfmpegHelper.java does not exist,start download"wget https://fs-im-kefu.7moor-fs1.com/29397395/4d2c3f00-7d4c-11e5-af15-41bf63ae4ea0/1705980395189/FfmpegHelper.java
fi# compile
if [ -e "/tmp/FfmpegHelper.class" ]
thenecho "FfmpegHelper.class already exist!"
elseecho "FfmpegHelper.class does not exist,start compile"javac FfmpegHelper.java
fi# run
java FfmpegHelper# clean
rm -rf /tmp/FfmpegHelper.class
rm -rf /tmp/FfmpegHelper.java

        FfmpegHelper.java

import java.io.File;public class FfmpegHelper {public static String GetDefaultFFMPEGPath() {return new File(System.getProperty("java.io.tmpdir"), "jave/").getAbsolutePath();}public static void main(String[] args) {String defaultFFMPEGPath = GetDefaultFFMPEGPath();System.out.println(defaultFFMPEGPath);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/424170.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

layui 自定义日期选择器今日、昨日 、本周、本月、上个月等

1、layui 日期选择器 laydate日期选择器 <div class"layui-input-inline"><input class"layui-input" id"dateTime" placeholder"日期范围"> </div><script> layui.use([laydate], function () {laydate.ren…

“libpng warning: iCCP: known incorrect sRGB profile” :图片或SVG加载不出来的问题,C++或Qt

加载图片时因为依赖第三方库缺失&#xff0c;报错&#xff01;&#xff01;&#xff01; ERROR或Warning : libpng warning: iCCP: known incorrect sRGB profile 然后我的解决办法也是网上大佬们的思路&#xff0c;在可执行同级目录下&#xff0c;放以下依赖库。 注意的地方…

【3.1数据库系统】数据库体系结构

目录 1.数据库模式2.关系表类型3.数据库视图4.分布式数据库 1.数据库模式 ①.外模式&#xff1a;外模式面向具体的应用程序&#xff0c;定义在逻辑模式之上&#xff0c;但独立于存储模式和存储设备。 ②.概念模式&#xff08;模式&#xff09;&#xff1a;用于描述数据库的逻辑…

Python爬虫框架选择与使用:推荐几个常用的高效爬虫框架

目录 前言 一、Scrapy框架 1. 安装Scrapy 2. Scrapy示例代码 3. 运行Scrapy爬虫 二、Beautiful Soup库 1. 安装Beautiful Soup 2. Beautiful Soup示例代码 3. 运行Beautiful Soup代码 三、Requests库 1. 安装Requests库 2. Requests示例代码 3. 运行Requests代码 …

6 时间序列(不同位置的装置如何建模): GRU+Embedding

很多算法比赛经常会遇到不同的物体产生同含义的时间序列信息&#xff0c;比如不同位置的时间序列信息&#xff0c;风力发电、充电桩用电。经常会遇到该如此场景&#xff0c;对所有数据做统一处理喂给模型&#xff0c;模型很难学到区分信息&#xff0c;因此设计如果对不同位置的…

TS的接口interface

接口 interface 1.基本概念 接口: 接口是TS设计出来用于定义对象类型的&#xff0c;可以对对象的形状进行描述。 定义interface一般首字母大写。 interface Person {name: stringage: number }const p1: Person {name: lin,age: 18 } 2.可选属性 跟函数的可选参数是类似…

ogg是什么文件格式?如何在车载u盘里播放?

Ogg&#xff0c;一种自由、开放的音频容器格式&#xff0c;起源于对数字音频的开源需求。由Xiph.Org基金会开发&#xff0c;其设计初衷是提供一种无损音频格式&#xff0c;可用于免费分发音乐&#xff0c;避免专有格式的限制。Ogg的产生背景反映了对数字音频共享的迫切需求。 o…

JDK8新特性(一)集合之 Stream 流式操作

1.Stream流由来 首先我们应该知道&#xff1a;Stream流的出现&#xff0c;主要是用在集合的操作上。在我们日常的工作中&#xff0c;经常需要对集合中的元素进行相关操作。诸如&#xff1a;增加、删除、获取元素、遍历。 最典型的就是集合遍历了。接下来我们先举个例子来看看 J…

grpcui安装使用

官网地址&#xff1a;https://github.com/fullstorydev/grpcui 安装命令&#xff1a; go get github.com/fullstorydev/grpcui go install github.com/fullstorydev/grpcui/cmd/grpcui ./bin/grpcui --import-path/home/xx/proto -proto xx.proto --plaintext 10.2.9.112:1…

Oracle Linux 9.3 安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

Linux下如何安装Redis及Another Redis Desktop Manager工具的简单使用

目录 Linux安装Redis笔记一、工具准备二、Redis下载三、Xftp和Xshell下载四、Liunx部署Redis4.1 解压Redis4.2 部署Redis4.2.1 说明文档4.2.2 相关设置4.2.3 操作4.2.4 查看redis.conf 配置4.2.5 Redis相关命令 五、Another Redis Desktop Manager 远程连接5.1 下载5.2 简单使用…

微信投票小程序源码系统 多功能强化版 带完整的安装部署教程

现如今&#xff0c;微信小程序的普及&#xff0c;越来越多的活动和比赛开始通过微信投票小程序进行。然而&#xff0c;市面上的投票小程序大多功能单一&#xff0c;不能满足各种复杂的需求。小编给大家分享一款微信投票小程序源码系统——多功能强化版。 以下是部分代码的示例…