ffmpeg视屏合成

明天你是否会想起 坐在你旁边的小弟 明天你是否还惦记 内存溢出的虚拟机
回想起粉笔的点点滴滴 我永远都难以忘记
是否能再给契机 让你我再相遇
致 chalk 、 我亲爱的豪哥
我转过我的脸 看不到你的眼 之前的消息你都没发现

方式一

package com.gluoh.file.ffmpeg;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class MergeFile {

    /**
     * 明天你是否会想起 坐在你旁边的小弟 明天你是否还惦记  内存溢出的虚拟机
     * 回想起粉笔的点点滴滴 我永远都难以忘记
     * 是否能再给契机  让你我再相遇
     *
     * 致 chalk 、 我亲爱的豪哥
     *
     * 我转过我的脸 看不到你的眼  之前的消息你都没发现
     *
     * **List<String> fromVideoFileList 需要合并的多视频url地址以List存放**
     * **String ffmpeg 此处是ffmpeg 配置地址,可写死如“E:/ffmpeg/bin/ffmpeg.exe”**
     * **String NewfilePath 合并后的视频存放地址,如:E:/mergevideo.mp4***
     */
    public static void convetor(List<String> fromVideoFileList, String ffmpeg,
                                String NewfilePath) throws IOException {
        new Thread(
                () -> {
                    try {
                        List<String> voidTS = new ArrayList<>();
                        Process process = null;
                        ProcessBuilder builder = null;
                        List<String> command = null;
                        for (int i = 0; i < fromVideoFileList.size(); i++) {
                            String fromVideoFile = fromVideoFileList.get(i);
                            command = new ArrayList<String>();
                            command.add(ffmpeg);
                            command.add("-y");
                            command.add("-i");
                            command.add(fromVideoFile);
                            command.add("-vcodec");
                            command.add("copy");
                            command.add("-bsf:v");
                            command.add("h264_mp4toannexb");
                            command.add("-f");
                            command.add("mpegts");
                            command.add(fromVideoFile.substring(0,
                                    fromVideoFile.lastIndexOf(".")) + ".ts");
                            builder = new ProcessBuilder(command);
                            voidTS.add(fromVideoFile.substring(0,
                                    fromVideoFile.lastIndexOf("."))
                                    + ".ts");
                            try {
                                process = builder.start();
                                InputStream errorStream = process
                                        .getErrorStream();
                                InputStreamReader inputStreamReader = new InputStreamReader(
                                        errorStream);
                                BufferedReader br = new BufferedReader(
                                        inputStreamReader);
                                String line = "";
                                StringBuffer sb = new StringBuffer();
                                while ((line = br.readLine()) != null) {
                                    sb.append(line);
                                }
                                String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
                                Pattern pattern = Pattern
                                        .compile(regexDuration);
                                Matcher m = pattern.matcher(sb.toString());
                                /*                     */
                                System.out.println(sb.toString());
                                br.close();
                                inputStreamReader.close();
                                errorStream.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        List<String> dos = new ArrayList<>();
                        StringBuffer tsPath = new StringBuffer();
                        tsPath.append(ffmpeg);
                        tsPath.append(" -i ");
                        tsPath.append("concat:");
                        for (int t = 0; t < voidTS.size(); t++) {
                            if (t != voidTS.size() - 1) {
                                tsPath.append(voidTS.get(t) + "|");
                            } else {
                                tsPath.append(voidTS.get(t));
                            }
                        }
                        tsPath.append(" -vcodec ");
                        tsPath.append(" copy ");
                        tsPath.append(" -bsf:a ");
                        tsPath.append(" aac_adtstoasc ");
                        tsPath.append(" -movflags ");
                        tsPath.append(" +faststart ");
                        tsPath.append(NewfilePath);
                        Process pr = Runtime.getRuntime().exec(
                                tsPath.toString());
                        process.getInputStream();
                        pr.getOutputStream().close();
                        pr.getInputStream().close();
                        pr.getErrorStream().close();
                        try {
                            pr.waitFor();
                            Thread.sleep(1000);
                            pr.destroy();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        //删除生成的ts文件
                        for (String filePath : voidTS) {
                            File file = new File(filePath);
                            file.delete();
                            pr.destroy();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }).start();
    }

    public static void main(String[] args) throws IOException {
        String ffmpeg = "E:\\dev-env\\ffmpeg\\bin\\ffmpeg.exe";
        String NewfilePath = "E:\\mergevideo.mp4";
        List fromVideoFileList = new ArrayList();
        fromVideoFileList.add("E:\\01.mp4");
        fromVideoFileList.add("E:\\02.mp4");
        convetor(fromVideoFileList, ffmpeg, NewfilePath);
    }

}

方式二-使用concat分离器合成视屏

   @ApiOperation(value = "视频合并", notes = "视频合并", response = Result.class)
    @PostMapping("/concatVideo")
    public Result concatVideo(
            @ApiParam(name = "files", value = "文件", required = true)
            @RequestParam("files") MultipartFile[] files) {
        List<Map<Integer, Object>> fileDatas = new ArrayList<>();
        Map<Integer, String> map = new HashMap<>();
        try {
            if (files != null && files.length > 0) {
                boolean b = false;
                for (int i=0;i<files.length;i++) {
                    /* 上传文件 */
                    String fileUrl = fastDFSClient.uploadFile(files[i]);
                    map.put(i,fileUrl);
                    /*视屏绝对路径*/
                    String veidoPath =temporaryPic+ fileUrl.replace("group1/M00/","");
                    /*视屏路径写入file.txt文件中*/
                    saveAsFileWriter("file '"+veidoPath+"'",b);
                    b =true;
                }
                /*文件输出路径*/
                String out = temporaryPic+ map.get(0).replace("group1/M00/","");
                /*视屏合并*/
                FirstFrameUtil.video(out);
                /*删除源文件*/
                for(Integer key:map.keySet()){
                    if(key != 0){
                        fastDFSClient.deleteFile(map.get(key));
                    }
                }
                return Result.success(map.get(0));
            }
        } catch (IOException e) {
            logger.error("上传文件异常:{}", ExceptionUtils.getStackTrace(e));
            return Result.error(ExceptionUtils.getMessage(e));
        }
        return Result.fail();
    }



//    private static String filePath = "/home/ffmpeg/file.txt";
    private static String filePath = "G:\\WeChat Files\\123.txt";

    private static void saveAsFileWriter(String content,boolean b) {
        System.out.println("文件路径--------"+content);
        FileWriter fwriter = null;
        try {
            // true表示不覆盖原来的内容,而是加到文件的后面。若要覆盖原来的内容,直接省略这个参数就好
            if(b){
                fwriter = new FileWriter(filePath, true);

            }else{
                fwriter = new FileWriter(filePath);
            }
            fwriter.write(content);
            fwriter.write("\n");

        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                fwriter.flush();
                fwriter.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

import java.io.File;
import java.util.List;

/**
 * @author xiaoqiang
 * @Description 视频第一帧处理工具
 * @date 2019/5/29 10:21
 */
public class FirstFrameUtil {
    //windows
    //private static  String FFMPEG_PATH = "D:/soft/ffmpeg/bin/ffmpeg.exe";
    //centos
    private static  String FFMPEG_PATH = "/usr/local/bin/ffmpeg";
    /**
     * FFmpeg
     * @param veidoPath
     * @return
     */
    public static boolean processImg(String veidoPath) {
        File file = new File(veidoPath);
        if (!file.exists()) {
            System.err.println("路径[" + veidoPath + "]对应的视频文件不存在!");
            return false;
        }
        List<String> commands = new java.util.ArrayList<String>();
        commands.add(FFMPEG_PATH);
        commands.add("-i");
        commands.add(veidoPath);
        commands.add("-y");
        commands.add("-f");
        commands.add("image2");
        commands.add("-ss");
        // 这个参数是设置截取视频多少秒时的画面
        commands.add("1");
        // commands.add("-t");
        // commands.add("0.001");
        commands.add("-s");
        commands.add("700x525");
        commands.add(veidoPath.substring(0, veidoPath.lastIndexOf("."))
                .replaceFirst("vedio", "file") + ".jpg");
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commands);
            builder.start();
            System.out.println("截取成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean video(String outPath) {
        File file = new File("/home/ffmpeg/file.txt");
        if (!file.exists()) {
            System.err.println("文件不存在!");
            return false;
        }
        List<String> commands = new java.util.ArrayList<String>();
        commands.add(FFMPEG_PATH);
        commands.add("-y");//覆盖元视屏
        commands.add("-f");
        commands.add("concat");
        commands.add("-safe");
        commands.add("0");
        commands.add("-i");
        commands.add("/home/ffmpeg/file.txt");
        commands.add("-c");
        commands.add("copy");
        commands.add(outPath);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commands);
            builder.start();
            System.out.println("合成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容

  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,044评论 0 4
  • 公元:2019年11月28日19时42分农历:二零一九年 十一月 初三日 戌时干支:己亥乙亥己巳甲戌当月节气:立冬...
    石放阅读 6,877评论 0 2