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

【音频处理】java流式调用ffmpeg命令

今天发现一个ffmpeg的用法,用子进程直接从标准输入写入输入,就可以从标准流式输出获取转码结果。
这样的好处是不用去写ffmpeg的代码,只需要写对ffmpeg的命令、在输入输出的地方加缓存就能进行流式转码了,方便快捷。
但是也有坏处,在开始的时候会引入几百ms的延时,到某个时间集体输出,后面的时间就正常了。

package ffmpegPro;
import java.io.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class Main {public static void main(String[] argv) {ExecutorService executor = Executors.newFixedThreadPool(8);Future<?> f1 = executor.submit(()->{progress("D:\\data\\audio\\a_out.wav","D:\\data\\audio\\a_output.pcm", executor);});Future<?> f2 = executor.submit(()->{progress("D:\\data\\audio\\b_out.wav","D:\\data\\audio\\b_output.pcm", executor);});try {f1.get();f2.get();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}executor.shutdown();}public static void progress(String inputPath, String outputPath, ExecutorService executor) {try {// 1. 定义 FFmpeg 命令(示例:H264 → VP9,实时转码)String[] ffmpegCmd = {"ffmpeg","-loglevel", "error","-hide_banner", "-nostats", //关闭日志"-f", "wav",      // 输入格式"-i", "pipe:0",    // 从标准输入读取"-f", "s16le",      // 输出格式"-acodec", "pcm_s16le","-ar", "8000",       // 16kHz"-ac", "1",           // 单声道"pipe:1"           // 输出到标准输出};// 2. 启动 FFmpeg 进程ProcessBuilder pb = new ProcessBuilder(ffmpegCmd);Process process = pb.start();// 3. 获取输入/输出流OutputStream ffmpegStdin = process.getOutputStream(); // FFmpeg 的 stdinInputStream ffmpegStdout = process.getInputStream(); // FFmpeg 的 stdoutInputStream ffmpegStderr = process.getErrorStream();  // FFmpeg 的 stderr(日志)// 4. 异步读取转码后的数据(防止阻塞)// 线程1:读取 FFmpeg 的输出(转码后的数据)executor.submit(() -> {byte[] buffer = new byte[8192];int bytesRead;try {FileOutputStream pcmFile = new FileOutputStream(outputPath);while ((bytesRead = ffmpegStdout.read(buffer)) != -1) {// 处理转码后的数据(示例:写入文件或推送到网络)System.out.println("收到转码数据,长度: " + bytesRead);pcmFile.write(buffer, 0, bytesRead);}} catch (IOException e) {e.printStackTrace();}});// 线程2:打印 FFmpeg 的错误日志(调试用)executor.submit(() -> {try (BufferedReader reader = new BufferedReader(new InputStreamReader(ffmpegStderr))) {String line;while ((line = reader.readLine()) != null) {System.err.println("[FFmpeg] " + line);}} catch (IOException e) {e.printStackTrace();}});// 5. 模拟向 FFmpeg 发送原始数据(示例:从文件读取)try (InputStream rawVideoStream = new FileInputStream(inputPath)) {byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = rawVideoStream.read(buffer)) != -1) {ffmpegStdin.write(buffer, 0, bytesRead);System.out.println("已发送原始数据,长度: " + bytesRead);}ffmpegStdin.close(); // 关闭输入流,通知 FFmpeg 结束} catch (IOException e) {e.printStackTrace();}// 6. 等待 FFmpeg 结束try {int exitCode = process.waitFor();System.out.println("FFmpeg 进程结束,退出码: " + exitCode);} catch (InterruptedException e) {e.printStackTrace();}} catch (Exception e) {e.printStackTrace();}}
}
http://www.lryc.cn/news/2393331.html

相关文章:

  • 《java创世手记》---java基础篇(下)
  • 【MySQL】C语言连接
  • How API Gateways handle raw TCP packets
  • 芯片配置文件自动化生成
  • 新能源汽车与油车销量
  • LVS-DR 负载均衡集群
  • 基于Java,SpringBoot,Vue,UniAPP宠物洗护医疗喂养预约服务商城小程序管理系统设计
  • 中车靶场,网络安全暑期实训营
  • 2.2.2 06年T1
  • split_conversion将json转成yolo训练用的txt,在直接按照8:1:1的比例分成训练集,测试集,验证集
  • 响应式系统与Spring Boot响应式应用开发
  • 【第1章 基础知识】1.8 在 Canvas 中使用 HTML 元素
  • c++流之sstream/堆or优先队列的应用[1]
  • SAR ADC 比较器噪声分析(二)
  • c#与java的相同点和不同点
  • phpmyadmin
  • 机器学习Day5-模型诊断
  • 如何将 WSL 的 Ubuntu-24.04 迁移到其他电脑
  • 金融欺诈有哪些检测手段
  • HTML5 全面知识点总结
  • vscode一直连接不上虚拟机或者虚拟机容器怎么办?
  • 初学c语言21(文件操作)
  • 数学复习笔记 21
  • 华为OD机试真题——数据分类(2025B卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
  • JavaWeb开发基础Servlet生命周期与工作原理
  • 三防平板科普:有什么特殊功能?应用在什么场景?
  • 百度外链生态的优劣解构与优化策略深度研究
  • 笔记: 在WPF中ContentElement 和 UIElement 的主要区别
  • 项目中使用到了多个UI组件库,也使用了Tailwindcss,如何确保新开发的组件样式隔离?
  • AI提示工程(Prompt Engineering)高级技巧详解