zoukankan      html  css  js  c++  java
  • 图片转字符图片(三)

    序言

    这个是从抖音上学来的,一开始刷抖音,遇到不少字符串跳舞的视频,因此来实践一下

    主要分为三个部分

    1. 静态图片转静态图片
    2. gif转gif
    3. 视频转视频

    视频转视频

    主要用到了FFmpeg这个工具,利用命令对视频文件进行操作。首先根据自己调的参数进行图片的截取(本文的是1秒10帧的参数),图片转换,然后分离音频,最后字符图片和音频合成目标视频。

    FFmpeg的代码库:
    https://github.com/FFmpeg/FFmpeg
    FFmpeg下载地址:
    https://ffmpeg.org/download.html

    主要用到的几个命令,其他按帧截图命令参考文末链接4:

    // 截图
    ffmpeg -ss 10 -i input.flv -y -f image2  -vframes 100 -s 352x240 b-%03d.jpg
    // 分离音频
    ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aac
    // 合成视频
    ffmpeg -threads2 -y -r 10 -i /tmpdir/image%04d.jpg -i audio.mp3 -absf aac_adtstoasc output.mp4
    

    环境:
    JDK 1.8

        // ffmpeg -ss 10 -i input.flv -y -f image2  -vframes 100 -s 352x240 b-%03d.jpg  
        /**
         * ffmpeg 截图,并指定图片的大小
         * 
         * @param srcVideoPath
         * @param tarImagePath
         *            截取后图片路径
         * @param width
         *            截图的宽
         * @param hight
         *            截图的高
         * @param offsetValue
         *            表示相对于文件开始处的时间偏移值 可以是分秒
         * @param vframes
         *            表示截图的桢数
         * 
         * @return
         */
        public static boolean processFfmpegImage(String srcVideoPath, String tarImagePath, int width, int hight,
                float offsetValue, float vframes) {
            if (!checkfile(srcVideoPath)) {
                System.out.println("【" + srcVideoPath + "】  不存在 !");
                // logger.error("【" + srcVideoPath + "】 不存在 !");
                return false;
            }
            List<String> commend = new java.util.ArrayList<String>();
    
            commend.add(ffmpegPath);
    
            commend.add("-i");
    
            commend.add(srcVideoPath);
    
            commend.add("-y");
    
            commend.add("-f");
    
            commend.add("image2");
    
            commend.add("-ss");
    
            commend.add(offsetValue + ""); // 在视频的某个插入时间截图,例子为5秒后
    
            // commend.add("-vframes");
    
            commend.add("-t");// 添加参数"-t",该参数指定持续时间
    
            commend.add(vframes + ""); // 截图的桢数,添加持续时间为1毫秒
    
            commend.add("-s");
    
            commend.add(width + "x" + hight); // 截图的的大小
    
            commend.add(tarImagePath);
    
            try {
                ProcessBuilder builder = new ProcessBuilder();
                builder.command(commend);
                builder.redirectErrorStream(true);
                // builder.redirectOutput(new File("F:/123/log/log.log"));
                Process process = builder.start();
                doWaitFor(process);
                process.destroy();
                if (!checkfile(tarImagePath)) {
                    System.out.println(tarImagePath + " is not exit!  processFfmpegImage 转换不成功 !");
                    // logger.info(tarImagePath + " is not exit! processFfmpegImage
                    // 转换不成功 !");
                    return false;
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("【" + srcVideoPath + "】 processFfmpegImage  转换不成功 !");
                // logger.error("【" + srcVideoPath + "】 processFfmpegImage 转换不成功
                // !");
                return false;
            }
        }
        
        public static boolean processFfmpegAudio(String srcVideoPath, String tarAudioPath) {
            if (!checkfile(srcVideoPath)) {
                System.out.println("【" + srcVideoPath + "】  不存在 !");
                // logger.error("【" + srcVideoPath + "】 不存在 !");
                return false;
            }
            // https://blog.csdn.net/xiaocao9903/article/details/53420519
            // ffmpeg -i 3.mp4 -vn -y -acodec copy 3.aac
            // ffmpeg -i 3.mp4 -vn -y -acodec copy 3.m4a
            
            List<String> commend = new java.util.ArrayList<String>();
            
            commend.add(ffmpegPath);
            
            commend.add("-i");
            
            commend.add(srcVideoPath);
            
            commend.add("-vn");
    
            commend.add("-y");
            
            commend.add("-acodec");
            
            commend.add("copy"); // 在视频的某个插入时间截图,例子为5秒后
            
            commend.add(tarAudioPath);
            
            try {
                ProcessBuilder builder = new ProcessBuilder();
                builder.command(commend);
                builder.redirectErrorStream(true);
                Process process = builder.start();
                doWaitFor(process);
                process.destroy();
                if (!checkfile(tarAudioPath)) {
                    System.out.println(tarAudioPath + " is not exit!  processFfmpegAudio 转换不成功 !");
                    return false;
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("【" + srcVideoPath + "】 processFfmpegAudio  转换不成功 !");
                return false;
            }
        }
    
        /**
         * ffmpeg 合成视频
         * 
         * @param srcVideoPath
         * @param tarImagePath
         *            截取后图片路径
         * @param width
         *            截图的宽
         * @param hight
         *            截图的高
         * @param offsetValue
         *            表示相对于文件开始处的时间偏移值 可以是分秒
         * @param vframes
         *            表示截图的桢数
         * 
         * @return
         */
        public static boolean processFfmpegVideo(String imagePath, String audioPath, String tarVideoPath, int step) {
            // https://blog.csdn.net/wangshuainan/article/details/77914508?fps=1&locationNum=4
            // 带音频
            // ffmpeg -threads2 -y -r 10 -i /tmpdir/image%04d.jpg -i audio.mp3 -absf
            // aac_adtstoasc output.mp4
    
            List<String> commend = new java.util.ArrayList<String>();
    
            commend.add(ffmpegPath);
    
            commend.add("-threads");
            
            commend.add("2");
    
            commend.add("-y");
    
            commend.add("-r");
    
            commend.add(step + "");
    
            commend.add("-i");
    
            commend.add(imagePath); // 图片
    
            commend.add("-i");
    
             commend.add(audioPath);
    
            commend.add("-absf");// 
    
            commend.add("aac_adtstoasc"); // 
    
            commend.add(tarVideoPath);
    
            try {
                ProcessBuilder builder = new ProcessBuilder();
                builder.command(commend);
                builder.redirectErrorStream(true);
                 builder.redirectOutput(new File("F:/123/log/log.log"));
                Process process = builder.start();
                doWaitFor(process);
                process.destroy();
                if (!checkfile(tarVideoPath)) {
                    System.out.println(tarVideoPath + " is not exit!  processFfmpegVideo 转换不成功 !");
                    return false;
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("【" + tarVideoPath + "】 processFfmpegVideo  转换不成功 !");
                return false;
            }
        }
    

    源码地址:
    https://github.com/Ruffianjiang/java4fun/tree/master/img2text

    参考:

    1. https://blog.csdn.net/i_likechard/article/details/79032931
    2. https://blog.csdn.net/xiaocao9903/article/details/53420519
    3. https://blog.csdn.net/wangshuainan/article/details/77914508?fps=1&locationNum=4
    4. https://blog.csdn.net/yourijing/article/details/50786758
  • 相关阅读:
    zookeeper.Net
    转码和解码
    Node.js开发Web后台服务
    SQL Server 2012 读写分离设置
    使用C# 和Consul进行分布式系统协调
    http2
    .net core 2.1.3可能引发Could not load file or assembly XXXXX的错误
    jquery on函数和prop与attr区别
    html页面中完成查找功能
    C#匿名参数(转载too)
  • 原文地址:https://www.cnblogs.com/lossingdawn/p/9509043.html
Copyright © 2011-2022 走看看