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 就有了,可以正常使用

在这里插入图片描述

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

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

相关文章

MongoDB复制(副本)集实战及原理分析

MongoDB复制集 复制集架构 在生产环境中&#xff0c;不建议使用单机版的MongoDB服务器。原因如下&#xff1a; 单机版的MongoDB无法保证可靠性&#xff0c;一旦进程发生故障或是服务器宕机&#xff0c;业务将直接不可用。一旦服务器上的磁盘损坏&#xff0c;数据会直接丢失&…

node.js中跨域请求有几种实现方法

默认情况下&#xff0c;出于安全考虑&#xff0c;浏览器会实施同源策略&#xff0c;阻止网页向不同源的服务器发送请求或接收来自不同源的响应。 同源策略&#xff1a;协议、域名、端口三者必须保持一致 <!DOCTYPE html> <html lang"en"> <head>&l…

无网通信 | 原理分析 / 应用

注&#xff1a;本文为“无网通信”相关几篇文章合辑。 到底什么是 “无网通信”&#xff1f; 原创 小枣君 鲜枣课堂 2024 年 10 月 30 日 18:18 江苏 最近智能手机市场迎来了一波发布热潮&#xff0c;在发布会现场&#xff0c;厂商们展示了令人眼花缭乱的各种参数和概念。其中…

PyQt事件机制及其应用

一、实例前置 一个小闹钟应用 创建主窗口类 首先我们创建了一个名为AlarmClock的类&#xff0c;它继承自QMainWindow。这个类将包含我们的GUI组件和逻辑。 from Alarm_clock import Ui_MainWindowclass AlarmClock(QMainWindow):def __init__(self):super().__init__()# 初始化…

福昕PDF低代码平台

福昕PDF低代码平台简介 福昕PDF 低代码平台是一款创新的工具&#xff0c;旨在简化PDF处理和管理的流程。通过这个平台&#xff0c;用户可以通过简单的拖拽界面上的按钮&#xff0c;轻松完成对Cloud API的调用工作流&#xff0c;而无需编写复杂的代码。这使得即使没有编程经验的…

Thonny IDE + MicroPython + ESP32 + 0.96寸OLED(IIC) 显示任意字符

四针脚0.96英寸OLED显示屏模块的具体参数如下表所示。 参数名称 参数特性 分辨率 128x64像素 通信方式 IIC 驱动芯片 SSD1306 屏幕颜色 白色、蓝色或黄蓝双色 元件&#xff1a; 四针脚0.96英寸OLED显示屏模块 ESP32 DEVKIT_C开发板 杜邦线USB Type-C 接线&#xf…

STM32HAL库入门教程——常用外设学习(1)

目录 学习外设前提——学习时钟树 一、时钟树是什么&#xff1f; 二、如何配置时钟树 三、时钟树的组成 3.1.时钟源 3.2.锁相环 PLL 3.3.系统时钟 SYSCLK 3.4.时钟信号输出 MCO 简单创建一个CubeMX工程&#xff08;STMF103常用&#xff09; 一、STM32HAL库开发&#…

方案拆解 | 打击矩阵新规频出!2025矩阵营销该怎么玩?

社媒平台的矩阵营销又要“变天”了&#xff1f;&#xff01; 11月18日&#xff0c;小红书官方发表了被安全薯 称为“小红书史上最严打击黑灰产专项”新规&#xff0c;其中就包括黑灰产矩阵号的公告。 ▲ 图源&#xff1a;小红书 实际上&#xff0c;不包括这次&#xff0c;今年…

系统思考—决策偏误

决策的质量&#xff0c;决定企业的未来。作为创办人&#xff0c;是不是也遇到过这样的困境&#xff1a;信息太多&#xff0c;团队收到的都是差不多的内容&#xff0c;甚至还有不少误导性的消息&#xff0c;结果一不小心做出了错误决策&#xff1f;尤其是在现在这个瞬息万变的环…

通过U盘启动盘安装Windows10操作系统步骤

主要包括以下几步&#xff1a; 1.U盘格式化&#xff0c;U盘容量要求不小于8G&#xff0c;如下图所示&#xff1a; 2.U盘启动盘制作&#xff1a; (1).进微软官网https://www.microsoft.com/zh-cn/software-download/windows10 下载MediaCreationTool_22H2.exe&#xff0c;以管理…

k8s-容器运行时接口分析

1、为了什么需要 CRI &#xff1f; 在 k8s v1.5 之前&#xff0c;Docker 作为第一代的容器运行时&#xff0c; kubelet 通过内嵌其中的 DockerShim 操作 Docker API 来操作容器。在 Kubernetes 1.5 中引入了 CRI&#xff0c;可以解耦了kubelet与容器运行时&#xff0c;该插件接…

【日常记录-Mybatis】PageHelper导致语句截断

1. 简介 PageHelper是Mybatis-Plus中的一个插件&#xff0c;主要用于实现数据库的分页查询功能。其核心原理是将传入的页码和条数赋值给一个Page对象&#xff0c;并保存到本地线程ThreadLocal中&#xff0c;接下来&#xff0c;PageHelper会进入Mybatis的拦截器环节&#xff0c;…

自回归模型(AR )

最近看到一些模型使用了自回归方法&#xff0c;这里就学习一下整理一下相关内容方便以后查阅。 自回归模型&#xff08;AR &#xff09; 自回归模型&#xff08;AR &#xff09;AR 模型的引入AR 模型的定义参数的估计方法模型阶数选择平稳性与因果性条件自相关与偏自相关函数优…

吉他初学者学习网站搭建系列(9)——如何用coze做一个网站助手

文章目录 背景功能搭建智能体新增工作流效果总结 背景 随着AI大模型的普及&#xff0c;国内也涌现出许多帮助用户更便捷使用大模型的平台。扣子就是其中之一。国内已经有蛮多用户了&#xff0c;我试用了这个平台&#xff0c;来给我的网站搭建一个小助手&#xff0c;效果非常好…

【网络】网络基础知识(协议、mac、ip、套接字)

文章目录 1. 计算机网络的背景2. 认识网络协议2.1 协议分层2.2 OS与网络的关系 3. 网络传输基本流程3.1 局域网通信流程3.2 跨网络通信流程 4. Socket 编程预备4.1 理解源IP地址和目的IP地址4.2 端口号与Socket4.3传输层的典型代表4.4 网络字节序 5. socket 编程接口5.1 介绍5.…

qtcanpool 知 08:Docking

文章目录 前言口味改造后语 前言 很久以前&#xff0c;作者用 Qt 仿照前端 UI 设计了一个 ministack&#xff08;https://gitee.com/icanpool/qtcanpool/blob/release-1.x/src/libs/qcanpool/ministack.h&#xff09; 控件&#xff0c;这个控件可以折叠。部分用户体验后&#…

【PyQt5教程 一】Qt Designer 安装及其使用方法说明,附程序源码

目录 一、PyQt5介绍&#xff1a; &#xff08;1&#xff09;PyQt简介&#xff1a; &#xff08;2&#xff09;PyQt API&#xff1a; &#xff08;3&#xff09;支持的环境&#xff1a; &#xff08;4&#xff09;安装&#xff1a; &#xff08;5&#xff09;配置环境变量…

青海摇摇了3天,技术退步明显.......

最近快手上的青海摇招聘活动非常火热&#xff0c;我已经在思考是否备战张诗尧的秋招活动。开个玩笑正片开始&#xff1a; 先说一下自己的情况&#xff0c;大专生&#xff0c;20年通过校招进入杭州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c…

DDD第一话:业务领域分析

业务领域的概念 业务领域定义了公司的主要活动领域&#xff0c;这是公司为客户提供的服务内容。例如&#xff1a;联邦快递提供快递服务&#xff1b;星巴克最出名的是它的咖啡。 子域 为了实现其业务领域的目标和目标&#xff0c;公司必须在多个子领域中操作。子域是业务活动…

MongoDB change stream实战

什么是 Chang Stream Change Stream指数据的变化事件流&#xff0c;MongoDB从3.6版本开始提供订阅数据变更的功能。 Change Stream 是 MongoDB 用于实现变更追踪的解决方案&#xff0c;类似于关系数据库的触发器&#xff0c;但原理不完全相同&#xff1a; Change Stream 的实…