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.mzph.cn/news/641425.shtml

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

相关文章

科技云报道:金融大模型落地,还需跨越几重山?

科技云报道原创。 时至今日&#xff0c;大模型的狂欢盛宴仍在持续&#xff0c;而金融行业得益于数据密集且有强劲的数字化基础&#xff0c;从一众场景中脱颖而出。 越来越多的公司开始布局金融行业大模型&#xff0c;无论是乐信、奇富科技、度小满、蚂蚁这样的金融科技公司&a…

深度学习如何弄懂那些难懂的数学公式?是否需要学习数学?

经过1~2年的学习&#xff0c;我觉得还是需要数学有一定认识&#xff0c;重新捡起高等数学、概率与数理、线代等这几本&#xff0c;起码基本微分方程、求导、对数、最小损失等等还是会用到。 下面给出几个链接&#xff0c;可以用于平时充电学习。 知乎上的&#xff1a; 机器学…

计算机毕业设计 基于SpringBoot的律师事务所案件管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

git merge和git rebase区别

具体详情 具体常见如下&#xff0c;假设有master和change分支&#xff0c;从同一个节点分裂&#xff0c;随后各自进行了两次提交commit以及修改。随后即为change想合并到master分支中&#xff0c;但是直接git commit和git push是不成功的&#xff0c;因为分支冲突了【master以…

上位机图像处理和嵌入式模块部署(流程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;传统图像处理的方法&#xff0c;一般就是pccamera的处理方式。camera本身只是提供基本的raw data数据&#xff0c;所有的…

基于ADAS的车道线检测算法matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 图像预处理 4.2 车道线特征提取 4.3 车道线跟踪 5.完整工程文件 1.课题概述 基于ADAS的车道线检测算法,通过hough变换和边缘检测方法提取视频样板中的车道线&#xff0c;然后根据车道线的弯曲情况…

《Python数据分析技术栈》第06章使用 Pandas 准备数据 13 分组和汇总 Grouping and aggregation

13 分组和汇总 Grouping and aggregation 《Python数据分析技术栈》第06章使用 Pandas 准备数据 13 分组和汇总 Grouping and aggregation Aggregation is the process of summarizing a group of values into a single value. 聚合是将一组值汇总为一个值的过程。 Hadley …

【 CSS 】精灵图、字体图标、CSS 三角、常用布局技巧

1. 精灵图&#xff08;重点&#xff09; 1.1 为何需要精灵图 一个网页中往往会应用很多小的背景图像作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度。 …

Linux/Mac 命令行工具 tree 开发项目结构可以不用截图了 更方便 更清晰 更全

tree 是一个命令行工具&#xff0c;用于以树形结构显示文件系统目录的内容。它可用于列出指定目录下的所有文件和子目录&#xff0c;以及它们的层次关系。tree 命令在许多操作系统中都可用&#xff0c;包括Unix、Linux和macOS。 效果如下&#xff1a; 一、安装 linux # De…

「Git」config 配置

Git 会自动跟踪是 谁 修改了项目&#xff0c;哪怕只是其中的一个字符&#xff0c;所以&#xff0c;Git需要配置用户的用户名以及邮箱地址。因此&#xff0c;在开始 Git 管理之前&#xff0c;我们可以先把 Git的用户设置配置一下【非必需&#xff0c;如果没有配置&#xff0c;Gi…

Prometheus+Grafana监控Mysql数据库

Promethues Prometheus https://prometheus.io Prometheus是一个开源的服务监控系统&#xff0c;它负责采集和存储应用的监控指标数据&#xff0c;并以可视化的方式进行展示&#xff0c;以便于用户实时掌握系统的运行情况&#xff0c;并对异常进行检测。因此&#xff0c;如何…

Ansible剧本playbooks

playbooks概述 Ansible剧本&#xff08;playbook&#xff09;是用于配置、部署和管理被控节点的一种描述文件。通过编写详细的剧本描述和执行其中的任务&#xff08;tasks&#xff09;&#xff0c;可以使远程主机达到预期的状态。剧本由一个或多个"play"组成的列表构…

Spring Boot3整合knife4j(swagger3)

目录 1.前置条件 2.导依赖 3.配置 1.前置条件 已经初始化好一个spring boot项目且版本为3X&#xff0c;项目可正常启动。 作者版本为3.2.2最新版 2.导依赖 knife4j官网&#xff1a; Knife4j 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j (xiaominfo.com)http…

CI/CD流水线插件在服务质量看护中的实践

一、前言 1、CI/CD CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付和持续部署。 作为一种面向开发和运维团队的解决方案&#xff0c;CI/CD 主要针对在集成新代码时所引发的问题&#xff08;亦称&#xff1a;“…

dnf:找不到命令

[rootecm-a08e ~]# sudo dnf install -y mysql-community-server sudo: dnf&#xff1a;找不到命令 [rootecm-a08e ~]# 在一些系统中&#xff0c;可能使用的是 yum 而不是 dnf 来进行包管理。请尝试使用 yum 命令安装 MySQL 8&#xff1a; sudo yum install -y mysql-communi…

R语言简介

1.R语言 R语言是一种数学编程语言&#xff0c;主要用于统计分析、绘图和数据挖掘。 2.R语言特点 免费、开源&#xff0c;兼容性好&#xff08;Windows、MacOS或Linux)。具有多种数据类型&#xff0c;如向量、矩阵、因子、数据集等常用数据结构。多用于交互式数据分析&#x…

股权众筹模式介绍(下)

3、线上线下两段式投资 对于已经成成立并运营的企业来说&#xff0c;由于《证券法》明确规定&#xff0c;向“不特定对象发行证券”以及“向特定对象发行证券累计超过200人”的行为属于公开发行证券&#xff0c;必须通过证监会核准&#xff0c;由证券公司承销。这些规定限定了…

RTDETR 引入 UniRepLKNet:用于音频、视频、点云、时间序列和图像识别的通用感知大卷积神经网络 | DRepConv

大卷积神经网络(ConvNets)近来受到了广泛研究关注,但存在两个未解决且需要进一步研究的关键问题。1)现有大卷积神经网络的架构主要遵循传统ConvNets或变压器的设计原则,而针对大卷积神经网络的架构设计仍未得到解决。2)随着变压器在多个领域的主导地位,有待研究ConvNets…

LED流水灯

这段代码是用于STM32F10x系列微控制器的程序&#xff0c;主要目的是初始化GPIOA并使其所有引脚按照特定的模式进行闪烁。下面是对这段代码的逐行解释&#xff1a; #include "stm32f10x.h"&#xff1a;这一行包含了STM32F10x系列微控制器的设备头文件。这个头文件包含…

《Python数据分析技术栈》第07章Python数据可视化 01 Matplotlib

01 Matplotlib 《Python数据分析技术栈》第07章Python数据可视化 01 Matplotlib In the last chapter, we read about Pandas, the library with various functions for preparing data in order to make it ready for analysis and visualization. Visualization is a means…