使用ffmpeg实现给音频,视频添加水印的操作

本文主要针对ffmpeg进行整理,从而解决在现实中可能存在的问题。

1.下载配置ffmpeg

这里参考的是

Java后台用ffmpeg命令给视频添加水印 - ^身后有尾巴^ - 博客园 (cnblogs.com)

1:先去ffmpeg官网下载其压缩包  Download FFmpeg

下载,解压到指定位置 

2.将压缩包拷贝到你想的任意位置并解压,正常解压出来的文件名过长,也可能会有空格,我们最好将文件夹下的文件拷贝出来到一个新的文件夹FFmpeg下

 3.配置环境变量

4.查看你的ffmpeg是否安装好,win+r 输入cmd,在里面输入ffmpeg -version,显示如下则安装成功

2.给视频添加水印

 1.在你的项目下新增工具类ProcessExec 一下是工具类里的代码

/**
 * @author JingJian
 * @version 1.0
 * @date 2022/2/10 14:43
 */

import com.baomidou.mybatisplus.toolkit.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ProcessExec {

    private Process process;

    public void execute(Map<String, String> dto) {
        StringBuffer waterlogo = new StringBuffer();
        waterlogo.append(" -i ");
//        输入文件
        if (null != dto.get("input_path") && StringUtils.isNotEmpty(dto.get("input_path"))) {
            waterlogo.append(dto.get("input_path"));
        }
        waterlogo.append("  -vf \"movie=");
//        添加的水印
        if (null != dto.get("logo") && StringUtils.isNotEmpty(dto.get("logo"))) {
            waterlogo.append(dto.get("logo"));
        }
        //        宽:高
        if (null != dto.get("wh") && StringUtils.isNotEmpty(dto.get("wh"))) {
            waterlogo.append(",scale= ");
            waterlogo.append(dto.get("wh"));
        }else{
            waterlogo.append(",scale= 60: 60");
        }
        waterlogo.append(" [watermark]; [in][watermark] overlay=main_w-overlay_w-10:main_h-overlay_h-10 [out]\" ");
        if (null != dto.get("video_converted_path") && StringUtils.isNotEmpty(dto.get("video_converted_path"))) {
            waterlogo.append(dto.get("video_converted_path"));
        }
        System.out.println(waterlogo);
        Runtime run = Runtime.getRuntime();
        String ffmegPath = null;
        if (StringUtils.isNotEmpty(dto.get("ffmpeg_path"))) {
            ffmegPath = dto.get("ffmpeg_path");
        }
// 执行命令
        try {
            System.out.println("执行的命令"+waterlogo);
            java.lang.Process process = run.exec(ffmegPath + waterlogo);
// 异步读取输出
            InputStream inputStream = process.getInputStream();
            InputStream errorStream = process.getErrorStream();
                    /* BufferedReader br=new BufferedReader(new InputStreamReader(inputStream,"gbk"));
                     String str1="";
                     while((str=br.readLine())!=null){
                         System.out.println(str1);
                     }*/

            ExecutorService service = Executors.newFixedThreadPool(2);

            ResultStreamHandler inputStreamHandler = new ResultStreamHandler(inputStream);
            ResultStreamHandler errorStreamHandler = new ResultStreamHandler(errorStream);

            service.execute(inputStreamHandler);
            service.execute(errorStreamHandler);

            process.waitFor();
            service.shutdownNow();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
2.新增控制台输入代码 ResultStreamHandler 
/**
 * @author JingJian
 * @version 1.0
 * @date 2022/2/10 14:45
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ResultStreamHandler
        implements Runnable {
    private InputStream inputStream;

    ResultStreamHandler( InputStream inputStream ) {
        this.inputStream = inputStream;
    }

    public void run() {

        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader( new InputStreamReader( inputStream,"gbk" ) );
            String line = null;

            while ( ( line = bufferedReader.readLine() ) != null ) {
                System.out.println( line );
            }
        }
        catch ( Throwable t ) {
        }
        finally {
            try {
                bufferedReader.close();
            }
            catch ( IOException e ) {
            }
        }
    }

}
3.CmdOutputGetter接口代码
public interface CmdOutputGetter {
    public void dealLine(String str);
}

4..调用添加水印工具类代码

/**
 * @author JingJian
 * @version 1.0
 * @date 2022/2/10 14:46
 * 视频添加水印logo
 */
import java.util.HashMap;

public class test {

    public static void main(String[] args) {
        ProcessExec ps = new ProcessExec();
        HashMap<String, String> dto=new HashMap<String, String>();
        //必填:此处是ffmpeg.exe所在位置,也就FFmpeg文件夹bin目录下的ffmpeg.exe
        dto.put("ffmpeg_path","D:\\myDemo\\tools\\ffmpeg\\bin\\ffmpeg.exe");
        //必填;此处是你要处理的视频位置
        dto.put("input_path", "D:\\myDemo\\tools\\MV\\test.mp4");
        //必填;此处是完成添加水印后输入视频的位置并重新命名该视频
        dto.put("video_converted_path", "D:\\myDemo\\tools\\MV\\TEST3.mp4");
        //必填;此处是你要添加的水印位置,注意此处图片位置一定要加上转译符,否则识别不了盘符
        dto.put("logo", "d\\\\:/myDemo/tools/MV/icon-my.png");
//        宽度:高度 (不是比例,是尺寸,默认 60:60)
        dto.put("wh", "80: 60");
        ps.execute(dto);
    }
}

3.给音频添加水印

1.首先maven引入第三方工具包:

<!-- 引入三方工具包 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.4.6</version>
</dependency>
<dependency> 
    <groupId>org</groupId>
    <artifactId>jaudiotagger</artifactId>
    <version>2.0.1</version>
</dependency>

2.创建一个工具类:AudioUtils,并添加以下方法


import org.jaudiotagger.audio.mp3.MP3AudioHeader;
import org.jaudiotagger.audio.mp3.MP3File;

/**
 * @author JingJian
 * @version 1.0
 * @date 2022/2/10 14:50
 */
public class AudioUtils {

//    public static String

    /**
     * 获取音频播放时长,返回值单位秒
     *
     * @param path 音频路径
     * @return
     */
    public static Integer getAudioDuration(String path) {
        try {
            MP3File file = new MP3File(path);
            MP3AudioHeader audioHeader = (MP3AudioHeader) file.getAudioHeader();
            return audioHeader.getTrackLength();
        } catch (Exception e) {
            System.out.println("获取音频播放时长失败!ERROR:{}");
            return null;
        }
    }
}

3.再创建一个工具类:CmdExecutor,用来执行FFmpeg指令

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * 脚本命令执行器
 * @author JingJian
 * @version 1.0
 * @date 2022/2/10 14:51
 */
public class CmdExecutor {

    /**
     * CMD操作
     * @param getter 获取控制台打印信息
     * @param cmd 命令
     */
    public static void exec(CmdOutputGetter getter, String... cmd) {
        try {
            // 创建新线程
            ProcessBuilder builder = new ProcessBuilder();
            // 执行命令
            builder.command(cmd);
            builder.redirectErrorStream(true);
            Process proc = builder.start();
            BufferedReader stdout = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line;
            while ((line = stdout.readLine()) != null) {
                if (getter != null)
                    getter.dealLine(line);
            }
            proc.waitFor();
            stdout.close();
        } catch (Exception e) {
        }
    }
}

4.测试代码

import org.junit.Test;
import java.io.File;
import java.util.Objects;

/**
 * 为音频添加水印
 * @author JingJian
 * @version 1.0
 * @date 2022/2/10 14:51
 */
//一般水印音频都是一段口播文字,可以到这个网站(https://www.zaixianai.cn/voiceCompose)去花去1块钱文字转语音一下
public class FFmpegTest {
    /**
     * 为音频文件添加水印
     * @param watermarkFilePath 水印文件路径
     * @param audioPath         源音频文件路径
     * @param ffmpegFile   ffmpeg程序位置
     */
    public static String addWatermark4Audio(String watermarkFilePath, String audioPath,String ffmpegFile) {
        // 获取源音频文件播放时长
        Integer duration = AudioUtils.getAudioDuration(audioPath);
        if (Objects.isNull(duration)) {
            System.out.println("获取音频文件时长失败");
            return audioPath;
        }
        System.out.println("源音频时长:" + duration);
        final String separator = File.separator;
        String newAudioPath =audioPath.substring(0,audioPath.lastIndexOf(separator)+1)+"w"+audioPath.substring(audioPath.lastIndexOf(separator)+1);
        String[] command4addWatermark = {ffmpegFile, "-i", audioPath, "-stream_loop", "-1", "-i", watermarkFilePath,
                "-filter_complex", "[1:a][0:a]amix", "-t", duration + "", "-ar", "48000", "-f", "mp3", newAudioPath,
                "-y"};
        CmdExecutor.exec(new CmdOutputGetter() {
            @Override
            public void dealLine(String line) {
                //把cmd输出的信息每行syso,这个是实时输出的,可以换其他的处理方式
                System.out.println(line);
            }
        }, command4addWatermark);

        System.out.println("添加音频水印完成!路径:" + newAudioPath);
        return newAudioPath.substring(newAudioPath.lastIndexOf(separator)+1);
    }

    @Test
    public void addWaterMark() {
        String ffmpegFile = "D:/myDemo/tools/ffmpeg/bin/ffmpeg.exe";
//        音频水印文件地址 会一直重复播放,如果需要间隔,可以使用格式工厂等制作间隔水印
        String watermarkFilePath = "C:/Users/admin/Music/音频水印/watermark.mp3";
        // 需要添加水印的音频文件
        String audioPath = "C:/Users/admin/Music/Paradise.mp3";
        // 添加水印
        addWatermark4Audio(watermarkFilePath, audioPath,ffmpegFile);
    }

}

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飓廴之莨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值