当前位置: 首页 > news >正文

ffmpeg转码与加水印

文章目录

    • 转码 与加水印
      • 引入jar包
      • 代码
      • ffmpeg安装
      • 错误
        • 解决方法

转码 与加水印

引入jar包

        <dependency><groupId>net.bramp.ffmpeg</groupId><artifactId>ffmpeg</artifactId><version>0.6.2</version></dependency>

代码

import lombok.extern.slf4j.Slf4j;
import net.bramp.ffmpeg.FFmpeg;
import net.bramp.ffmpeg.builder.FFmpegBuilder;
import net.bramp.ffmpeg.job.FFmpegJob;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;/*** @description 阿里云文件上传** @author lilinchun* @date 2024/10/17*/
@Slf4j
public class OssUtil {public static void main(String[] args) {String videoUrl = "xxx.mp4";try {convertAndUpload(videoUrl);} catch (Exception e) {e.printStackTrace();System.err.println("转换和上传失败: " + e.getMessage());}}/*** 将mp4文件url地址转换并上传到oss中* @param url mp4地址* @return m3u8文件地址*/public static String convertAndUpload(String url) throws Exception {String vodId = null;// 截取文件名称String fileName = url.substring(url.lastIndexOf('/') + 1);int lastDotIndex = fileName.lastIndexOf('.');String name = fileName.substring(0, lastDotIndex);String fileNameNew = name+"mark"+".mp4";// 当前项目的文件路径Path tempDir = Files.createTempDirectory("ffmpeg-temp");Path inputFilePath = tempDir.resolve(fileName);Path inputFilePathWatermark = tempDir.resolve(fileNameNew);Path outputM3U8Path = tempDir.resolve(name + ".m3u8");// 创建TS文件输出目录Path outputTSDir = tempDir.resolve(name + "_ts");Files.createDirectories(outputTSDir);log.info("临时文件路径:{}", tempDir.toString());try {downloadFileNew(url, tempDir.toString());// 设置水印watermarkVoid(inputFilePath,inputFilePathWatermark);// 转换生成M3U8和TS文件  指定播放片段为20sString ffmpegCommand = String.format("ffmpeg -i %s -codec: copy -start_number 0 -hls_time 20 -hls_list_size 0 -f hls -hls_segment_filename %s/%s_%%03d.ts %s",inputFilePathWatermark.toAbsolutePath(),outputTSDir.toAbsolutePath(),name,outputM3U8Path.toAbsolutePath());// 执行FFmpeg命令转换视频Process process = Runtime.getRuntime().exec(ffmpegCommand);process.waitFor();String indexFile = outputM3U8Path.toString();List<String> tsFiles = new ArrayList<>();System.out.println("解析文件路径地址:" + outputM3U8Path);for (int i = 0; ; i++) {Path tsFilePath = outputTSDir.resolve(String.format("%s_%03d.ts", name, i));if (!Files.exists(tsFilePath)) {break;}System.out.println("解析文件路径ts地址:" + tsFilePath);tsFiles.add(tsFilePath.toString());}// 上传阿里云视屏点播服务vodId = UploadVodByApi.uploadVideo(indexFile, tsFiles, name + ".m3u8");// 清理临时文件cleanup(tempDir);log.info("临时文件路径:{}", tempDir.toString());} catch (IOException e) {e.printStackTrace();log.error("文件转换失败:{}", e.getMessage());}return vodId;}/*** 设置视屏水印* @param inputFilePath 原始视屏路径* @param inputFilePathWatermark  水印视屏路径*/private static void watermarkVoid(Path inputFilePath,Path inputFilePathWatermark){log.info("文件名称:{},{}",inputFilePath.toAbsolutePath(),inputFilePathWatermark.toAbsolutePath());// 构建FFmpeg命令String ffmpegCommandWatermark = String.format("ffmpeg -i \"%s\" -vf \"drawtext=text='nk.benwunet.com':x=mod(n\\,w+tw)-tw:y=10:fontsize=24:fontcolor=white\" -codec:a copy \"%s\"",inputFilePath.toAbsolutePath(),inputFilePathWatermark.toAbsolutePath());log.info("执行加水印的命令:{}",ffmpegCommandWatermark);try {// 使用ProcessBuilder来启动外部进程// 使用ProcessBuilder来启动外部进程ProcessBuilder processBuilder = new ProcessBuilder("ffmpeg", "-i", inputFilePath.toAbsolutePath().toString(),"-vf", "drawtext=text='nk.benwunet.com':x=mod(n\\,w+tw)-tw:y=10:fontsize=24:fontcolor=white","-codec:a", "copy",inputFilePathWatermark.toAbsolutePath().toString());// 将错误输出重定向到标准输出processBuilder.redirectErrorStream(true);Process process = processBuilder.start();// 读取输出BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {log.info(line);}// 等待进程完成int exitCode = process.waitFor();if (exitCode == 0) {log.info("Video watermarking completed successfully.");} else {log.error("FFmpeg command failed with exit code: " + exitCode);}// 关闭资源reader.close();}catch (Exception e){log.error("Error occurred while processing the video: ", e);}}/*** 下载文件* @param urlStr 文件地址* @param saveDir 文件路径* @throws IOException 异常*/public static void downloadFileNew(String urlStr, String saveDir) throws IOException {CloseableHttpClient httpClient = HttpClientSingleton.getInstance();HttpGet request = new HttpGet(urlStr);try (CloseableHttpResponse response = httpClient.execute(request)) {int responseCode = response.getStatusLine().getStatusCode();if (responseCode == 200) {String fileName = urlStr.substring(urlStr.lastIndexOf('/') + 1);String saveFilePath = saveDir + File.separator + fileName;try (InputStream inputStream = response.getEntity().getContent();FileOutputStream outputStream = new FileOutputStream(saveFilePath)) {byte[] buffer = new byte[4096];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}}} else {throw new IOException("No file to download. Server replied HTTP code: " + responseCode);}}}/*** 清理文件* @param dir 文件地址  示例:/tmp/ffmpeg-temp9193762578321295193* @throws IOException 异常*/private static void cleanup(Path dir) throws IOException {Files.walk(dir)// 逆序遍历,先删除子文件.sorted((a, b) -> -a.compareTo(b)).forEach(path -> {try {Files.delete(path);} catch (IOException e) {e.printStackTrace();}});}}

ffmpeg安装

可以安装宝塔的

1、安装管理器
在这里插入图片描述
2、安装ffmpeg的版本

3、测试

检查版本

ffmpeg -version

在这里插入图片描述

错误

No such filter: ‘drawtext’
[vost#0:0/libx264 @ 0x7eabd00] Error initializing a simple filtergraph
Error opening output file 01mark.mp4

转码中使用到了drawtext,但是ffmpeg并没有drawtext,所以报错了

解决方法

1、确认FFmpeg版本
确保你安装的FFmpeg版本支持drawtext滤镜。运行以下命令来查看所有可用的滤镜:

ffmpeg -filters

在这里插入图片描述
我之前是安装的ffmpeg-6.1 发现没有这个滤镜,之后我安装了ffmpeg-4.4.1 就有了,可以正常使用

在这里插入图片描述

相关文章:

ffmpeg转码与加水印

文章目录 转码 与加水印引入jar包代码ffmpeg安装错误解决方法 转码 与加水印 引入jar包 <dependency><groupId>net.bramp.ffmpeg</groupId><artifactId>ffmpeg</artifactId><version>0.6.2</version></dependency>代码 impo…...

Leetcode 104. 二叉树的最大深度(Java-深度遍历)

题目描述&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;…...

阳明心学-传习录学习总结

资料 王阳明介绍&#xff1a;明代杰出的思想家、军事家、教育家&#xff1b;自刑部主事历任贵州龙场驿丞、庐陵知县、右佥都御史、南赣巡抚、两广总督等职&#xff0c;接连平定南赣、两广盗乱及宸濠之乱&#xff0c;因功获封“新建伯”&#xff0c;成为明代因军功封爵的三位文…...

macOS sequoia 15.1中应用程序“程序坞”没有权限打开

在macOS sequoia 15.1版本中新安装的应用程序在访达中打开报错显示应用程序“程序坞”没有权限打开“(null)”。 解决办法 在启动台中找到终端&#xff0c;点击打开&#xff0c;切换到应用目录下&#xff0c;输入 cd /Applications/ 找到需要打开的应用程序目录&#xff0…...

使用 MinIO 和 KKFileView 实现在线文件预览功能

在项目开发中&#xff0c;文件的在线预览是常见的需求&#xff0c;尤其是对 PDF、Word、Excel 等格式的文件进行无客户端依赖的直接查看。本文将介绍如何通过 MinIO 和 KKFileView 搭建在线文件预览服务&#xff0c;并通过 docker-compose 一键部署。 一、环境准备 1. Docker …...

Conda-Pack打包:高效管理Python环境

在Python开发中&#xff0c;环境管理是一个不可忽视的重要环节。Conda是一个流行的包管理器和环境管理器&#xff0c;它允许用户创建隔离的环境&#xff0c;以避免不同项目之间的依赖冲突。Conda-pack是一个工具&#xff0c;可以帮助我们将一个conda环境打包成一个可移植文件&a…...

云服务器上搭建 WordPress 全流程指南

WordPress 是全球最受欢迎的开源内容管理系统&#xff08;CMS&#xff09;&#xff0c;通过 WordPress&#xff0c;你可以轻松搭建博客、企业网站或电子商务平台。而通过云服务器搭建 WordPress&#xff0c;可以使网站获得更好的性能和灵活性。本文将为你提供详细的步骤&#x…...

图像超分辨率技术新进展:混合注意力聚合变换器HAAT

目录 1. 引言&#xff1a; 2. 混合注意力聚合变换器&#xff08;HAAT&#xff09;&#xff1a; 2.1 Swin-Dense-Residual-Connected Block&#xff08;SDRCB&#xff09;&#xff1a; 2.2 Hybrid Grid Attention Block&#xff08;HGAB&#xff09;&#xff1a; 3. 实验结…...

文件IO——01

1. 认识文件 1&#xff09;文件概念 “文件”是一个广义的概念&#xff0c;可以代表很多东西 操作系统里&#xff0c;会把很多的硬件设备和软件资源抽象成“文件”&#xff0c;统一管理 但是大部分情况下的文件&#xff0c;都是指硬盘的文件&#xff08;文件相当于是对“硬…...

【opencv入门教程】5. Mat 类用法

文章选自&#xff1a; 一、BackGround Mat对象是一种图像数据结构&#xff0c;它是一个容器&#xff0c;存储任何通道任何数的图片数据以及对应的矩阵&#xff0c;使用完成后&#xff0c;内存自动释放。二、Code void Samples::MatFunc() {1. 图像处理// 方法1&#xff1a;…...

SSM虾米音乐项目2--分页查询

1.分页查询的底层逻辑 首先根据用户输入的流派&#xff0c;进行模糊查询根据查询的数据进行分页需要前端用户提供pageNo(当前页数)和pageSize(每页的数据量)并且要从后端计算count(总数据量)和totalPage(总页数)&#xff0c;以及startNum(每页开始的记录)从而将对应的页面数据…...

nodejs 获取本地局域网 ip 扫描本地端口

因为傻逼老板的垃圾需求&#xff0c;不得不成长 示例代码&#xff1a; 获取本地局域网 ip 地址&#xff1a; 需要注意的是&#xff1a;如果存在虚拟机网络&#xff0c;则返回的是虚拟机网络的 ipv4 地址 import os from os; export const getLocalIp () > {const in…...

区块链签名种类

1. eth_sign 简介&#xff1a;最早实现的签名方法&#xff0c;用于对任意数据进行签名。签名内容&#xff1a;直接对原始消息的哈希值进行签名。特点&#xff1a; 安全性较低&#xff0c;因为签名的消息没有明确的上下文或结构。很容易被滥用&#xff0c;攻击者可以伪造签名内…...

【062B】基于51单片机无线病房呼叫系统(+时间)【Keil程序+报告+原理图】

☆、设计硬件组成&#xff1a;51单片机最小系统NRF24L01无线模块DS1302时钟芯片LCD1602液晶显示按键设置蜂鸣器LED灯。 1、本设计采用STC89C51/52、AT89C51/52、AT89S51/52作为主控芯片&#xff0c;采用LCD1602液晶显示呼叫信息&#xff0c;系统共有两个板子&#xff08;一个接…...

突破空间限制!从2D到3D:北大等开源Lift3D,助力精准具身智能操作!

文章链接&#xff1a;https://arxiv.org/pdf/2411.18623 项目链接&#xff1a;https://lift3d-web.github.io/ 亮点直击 提出了Lift3D&#xff0c;通过系统地提升隐式和显式的3D机器人表示&#xff0c;提升2D基础模型&#xff0c;构建一个3D操作策略。 对于隐式3D机器人表示&a…...

【pyspark学习从入门到精通24】机器学习库_7

目录 聚类 在出生数据集中寻找簇 主题挖掘 回归 聚类 聚类是机器学习中另一个重要的部分&#xff1a;在现实世界中&#xff0c;我们并不总是有目标特征的奢侈条件&#xff0c;因此我们需要回归到无监督学习的范式&#xff0c;在那里我们尝试在数据中发现模式。 在出生数据…...

Echart折线图属性设置 vue2

Echart折线图 官方配置项手册 Documentation - Apache ECharts 下面代码包含&#xff1a;设置标题、线条样式、图例圆圈的样式、显示名称格式、图片保存、增加Y轴目标值 updateChart(data) {const sortedData data.slice().sort((a, b) > new Date(a.deviceTime) - ne…...

LabVIEW-简单串口助手

LabVIEW-简单串口助手 串口函数VISA配置串口VISA写入函数VISA读取函数VISA资源名称按名称解除捆绑 函数存放位置思维导图主体界面为以下 串口函数 VISA配置串口 VISA写入函数 VISA读取函数 VISA资源名称 按名称解除捆绑 函数存放位置 思维导图 主体界面为以下 从创建好的“枚举…...

Linux下,用ufw实现端口关闭、流量控制(二)

本文是 网安小白的端口关闭实践 的续篇。 海量报文&#xff0c;一手掌握&#xff0c;你值得拥有&#xff0c;让我们开始吧&#xff5e; ufw 与 iptables的关系 理论介绍&#xff1a; ufw&#xff08;Uncomplicated Firewall&#xff09;是一个基于iptables的前端工具&#xf…...

C#开发-集合使用和技巧(九)Join的用法

在C#中&#xff0c;IEnumerable 的 Join 方法用于根据键将两个序列中的元素进行关联。Join 方法通常用于执行类似于 SQL 中的内连接操作。以下是 Join 方法的基本用法&#xff1a; 基本语法 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...