如何通过Java调用ffmpeg实现带水印视频的Web端流式服务?
解决方案
一、添加个性化水印的FFmpeg命令
先通过FFmpeg的drawtext滤镜生成带个人信息的水印视频,命令示例如下(可根据需求调整位置、字体、透明度):
ffmpeg -i input.mp4 -vf "drawtext=text='用户ID:12345':fontsize=24:fontcolor=white@0.7:x=w-tw-10:y=h-th-10" -c:v libx264 -c:a copy -y output_watermarked.mp4
参数说明:
-vf "drawtext=...":视频滤镜,指定水印文本、大小、颜色、透明度及右下角位置-c:a copy:复用原音频流,减少处理时间-y:自动覆盖已存在的输出文件
二、Java通过Runtime#exec调用FFmpeg
Java中调用FFmpeg需注意处理进程的输入输出流(避免阻塞),示例代码如下:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class FfmpegWatermarkHandler { public static void generateWatermarkedVideo(String inputPath, String outputPath, String userInfo) throws IOException, InterruptedException { // 构建FFmpeg命令数组 String[] cmd = { "ffmpeg", "-i", inputPath, "-vf", String.format("drawtext=text='%s':fontsize=24:fontcolor=white@0.7:x=w-tw-10:y=h-th-10", userInfo), "-c:v", "libx264", "-c:a", "copy", "-y", outputPath }; // 启动进程并处理流 Process process = Runtime.getRuntime().exec(cmd); // 异步处理FFmpeg标准输出 new Thread(() -> { try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { // 可记录日志 System.out.println("FFmpeg日志: " + line); } } catch (IOException e) { e.printStackTrace(); } }).start(); // 异步处理FFmpeg错误输出 new Thread(() -> { try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { String line; while ((line = reader.readLine()) != null) { // 记录错误日志 System.err.println("FFmpeg错误: " + line); } } catch (IOException e) { e.printStackTrace(); } }).start(); // 等待命令执行完成 int exitCode = process.waitFor(); if (exitCode != 0) { throw new RuntimeException("视频加水印失败,FFmpeg退出码: " + exitCode); } } }
推荐使用
ProcessBuilder替代Runtime#exec,它支持设置工作目录、环境变量,还能合并输出/错误流,更易维护。
三、让Web端访问带水印的视频输出
无需依赖ffserver,有两种简便方案:
1. 文件输出 + Java静态资源服务
生成带水印的视频文件后,将输出目录配置为Java后端的静态资源目录。比如Spring Boot中配置:
spring: web: resources: static-locations: file:/path/to/watermarked-videos/
前端通过HTTP直接访问:http://your-backend-domain/videos/output_watermarked.mp4
2. 实时流输出 + 轻量HTTP转发
用FFmpeg将带水印的视频实时推流到Java后端的HTTP端点,再由后端转发给前端。示例FFmpeg命令:
ffmpeg -i input.mp4 -vf "drawtext=text='用户ID:12345':fontsize=24:fontcolor=white@0.7:x=w-tw-10:y=h-th-10" -c:v libx264 -c:a copy -f flv http://localhost:8080/stream
Java后端可基于Netty或Jetty搭建简单的HTTP服务器接收FLV流,再转成浏览器支持的格式(如HLS)供前端播放。
四、FFmpeg能否直接作为服务器供Web端访问?
FFmpeg本身不是专门的Web/流媒体服务器,仅提供基础的协议监听能力(如RTSP的-listen 1参数),不适合生产环境的Web访问:
- 它的HTTP服务功能极简,无缓存、权限控制、负载均衡等Web必备特性
- 浏览器原生支持的HLS/DASH流媒体协议,FFmpeg仅能生成对应分片文件,无法直接提供服务
更稳妥的方案是:Java调用FFmpeg生成带水印的视频/流,配合Java后端或Nginx作为Web服务层,提供带权限控制的视频访问入口。
额外防抄袭建议:除水印外,可配合动态签名URL(带过期时间)、视频分片加密、前端登录鉴权等方式,进一步限制未经授权的下载与分享。
内容的提问来源于stack exchange,提问作者Jose A. Matarán
相关产品推荐
相关产品推荐

