zoukankan      html  css  js  c++  java
  • 「小程序JAVA实战」小程序视频处理工具ffmpeg(47)

    转自;https://idig8.com/2018/09/16/xiaochengxujavashizhanxiaochengxushipinchuligongjuffmpeg46/

    前面已经把视频成功的上传到我们的服务器,选择了背景音乐的ID,现在需要把视频和背景音乐进行合并,需要使用一个工具ffmpeg。源码:https://github.com/limingios/wxProgram.git 中wx-springboot 和 No.15

    ffmpeg

    • 介绍
      >视音频处理工具,跨平台的视音频处理解决方案,主页:http://ffmpeg.org

    • 应用的场景
    1. 播放器:射手播放器,暴风影音,迅雷播放器……
    2. 转换工具:格式工厂,剪辑工具……
    3. 直播,视频加码,滤镜,水印,特效……
    • 下载

    根据你的需求进行下载,我选择在windows平台来进行下载

    • 测试

    C:UsersAdministrator>D:
    
    D:>cd D:Program Filesffmpeg
    
    D:Program Filesffmpeg>cd bin
    
    D:Program Filesffmpegin>ffmpeg.exe -i shanzhu.mp4 shanzhu.avi
    ffmpeg version N-91949-g6304268e39 Copyright (c) 2000-2018 the FFmpeg developers
      built with gcc 8.2.1 (GCC) 20180813
      configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth
      libavutil      56. 19.101 / 56. 19.101
      libavcodec     58. 30.100 / 58. 30.100
      libavformat    58. 18.100 / 58. 18.100
      libavdevice    58.  4.103 / 58.  4.103
      libavfilter     7. 31.100 /  7. 31.100
      libswscale      5.  2.100 /  5.  2.100
      libswresample   3.  2.100 /  3.  2.100
      libpostproc    55.  2.100 / 55.  2.100
    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'shanzhu.mp4':
      Metadata:
        major_brand     : mp42
        minor_version   : 1
        compatible_brands: mp41mp42isom
        creation_time   : 2018-09-16T05:29:47.000000Z
      Duration: 00:00:09.34, start: 0.000000, bitrate: 1210 kb/s
        Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 544x960, 1159 kb/s, 29.97 fps, 29.97 tbr, 600 tbn, 1200 tbc (default)
        Metadata:
          creation_time   : 2018-09-16T05:29:47.000000Z
          handler_name    : Core Media Video
        Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 46 kb/s (default)
        Metadata:
          creation_time   : 2018-09-16T05:29:47.000000Z
          handler_name    : Core Media Audio
    Stream mapping:
      Stream #0:0 -> #0:0 (h264 (native) -> mpeg4 (native))
      Stream #0:1 -> #0:1 (aac (native) -> mp3 (libmp3lame))
    Press [q] to stop, [?] for help
    Output #0, avi, to 'shanzhu.avi':
      Metadata:
        major_brand     : mp42
        minor_version   : 1
        compatible_brands: mp41mp42isom
        ISFT            : Lavf58.18.100
        Stream #0:0(und): Video: mpeg4 (FMP4 / 0x34504D46), yuv420p, 544x960, q=2-31, 200 kb/s, 29.97 fps, 29.97 tbn, 29.97 tbc (default)
        Metadata:
          creation_time   : 2018-09-16T05:29:47.000000Z
          handler_name    : Core Media Video
          encoder         : Lavc58.30.100 mpeg4
        Side data:
          cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
        Stream #0:1(und): Audio: mp3 (libmp3lame) (U[0][0][0] / 0x0055), 44100 Hz, mono, fltp (default)
        Metadata:
          creation_time   : 2018-09-16T05:29:47.000000Z
          handler_name    : Core Media Audio
          encoder         : Lavc58.30.100 libmp3lame
    frame=  280 fps=0.0 q=31.0 Lsize=    1096kB time=00:00:09.34 bitrate= 961.3kbits/s speed=16.7x
    video:999kB audio:72kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 2.338377%
    
    

    • java程序调用cmd转换视频

    springboot-common中添加FFMpegTest

    package com.idig8.utils;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class FFMpegTest {
    
        private String ffmpegEXE;
    
        public FFMpegTest(String ffmpegEXE) {
            super();
            this.ffmpegEXE = ffmpegEXE;
        }
    
        public void convertor(String videoInputPath, String videoOutputPath) throws Exception {
    //      ffmpeg -i input.mp4 -y output.avi
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
    
            command.add("-i");
            command.add(videoInputPath);
            command.add("-y");
            command.add(videoOutputPath);
    
            for (String c : command) {
                System.out.print(c + " ");
            }
    
            ProcessBuilder builder = new ProcessBuilder(command);
            Process process = builder.start();
    
            InputStream errorStream = process.getErrorStream();
            InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
            BufferedReader br = new BufferedReader(inputStreamReader);
    
            String line = "";
            while ( (line = br.readLine()) != null ) {
            }
    
            if (br != null) {
                br.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (errorStream != null) {
                errorStream.close();
            }
    
        }
    
        public static void main(String[] args) {
            FFMpegTest ffmpeg = new FFMpegTest("D:\Program Files\ffmpeg\bin\ffmpeg.exe");
            try {
                ffmpeg.convertor("D:\Program Files\ffmpeg\bin\shanzhu.mp4", "D:\Program Files\ffmpeg\bin\shanzhu.avi");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    
    
    • 视频音频合并命令
      > 通过这种方式,可以让我们的mp4和我们的mp3 做一个结合。
    ffmpeg.exe -i shanzhu.avi -i music.mp3 -t 10 -y 合并音乐和视频.avi
    

    D:Program Filesffmpegin>ffmpeg.exe -i shanzhu.avi -i music.mp3 -t 10 -y 合并音乐和视频.avi
    ffmpeg version N-91949-g6304268e39 Copyright (c) 2000-2018 the FFmpeg developers
      built with gcc 8.2.1 (GCC) 20180813
      configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth
      libavutil      56. 19.101 / 56. 19.101
      libavcodec     58. 30.100 / 58. 30.100
      libavformat    58. 18.100 / 58. 18.100
      libavdevice    58.  4.103 / 58.  4.103
      libavfilter     7. 31.100 /  7. 31.100
      libswscale      5.  2.100 /  5.  2.100
      libswresample   3.  2.100 /  3.  2.100
      libpostproc    55.  2.100 / 55.  2.100
    Input #0, avi, from 'shanzhu.avi':
      Metadata:
        encoder         : Lavf58.18.100
      Duration: 00:00:09.38, start: 0.000000, bitrate: 957 kb/s
        Stream #0:0: Video: mpeg4 (Simple Profile) (FMP4 / 0x34504D46), yuv420p, 544x960 [SAR 1:1 DAR 17:30], 876 kb/s, 29.97 fps, 29.97 tbr, 29.97 tbn, 30k tbc
        Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 44100 Hz, mono, fltp, 64 kb/s
    [mp3 @ 000001fcfa57d6c0] Estimating duration from bitrate, this may be inaccurate
    Input #1, mp3, from 'music.mp3':
      Duration: 00:00:33.47, start: 0.000000, bitrate: 320 kb/s
        Stream #1:0: Audio: mp3, 48000 Hz, stereo, fltp, 320 kb/s
    Stream mapping:
      Stream #0:0 -> #0:0 (mpeg4 (native) -> mpeg4 (native))
      Stream #1:0 -> #0:1 (mp3 (mp3float) -> mp3 (libmp3lame))
    Press [q] to stop, [?] for help
    Output #0, avi, to '鍚堝苟闊充箰鍜岃�棰?avi':
      Metadata:
        ISFT            : Lavf58.18.100
        Stream #0:0: Video: mpeg4 (FMP4 / 0x34504D46), yuv420p(progressive), 544x960 [SAR 1:1 DAR 17:30], q=2-31, 200 kb/s, 29.97 fps, 29.97 tbn, 29.97 tbc
        Metadata:
          encoder         : Lavc58.30.100 mpeg4
        Side data:
          cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
        Stream #0:1: Audio: mp3 (libmp3lame) (U[0][0][0] / 0x0055), 48000 Hz, stereo, fltp
        Metadata:
          encoder         : Lavc58.30.100 libmp3lame
    frame=  280 fps=274 q=31.0 Lsize=    1076kB time=00:00:10.00 bitrate= 880.4kbits/s speed=9.79x
    video:892kB audio:157kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 2.510280%
    
    • java程序调用cmd转换视频增加音频
    package com.idig8.utils;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class MergeVideoMp3 {
    
        private String ffmpegEXE;
    
        public MergeVideoMp3(String ffmpegEXE) {
            super();
            this.ffmpegEXE = ffmpegEXE;
        }
    
        public void convertor(String videoInputPath, String mp3InputPath,
                double seconds, String videoOutputPath) throws Exception {
    //      ffmpeg.exe -i 苏州大裤衩.mp4 -i bgm.mp3 -t 7 -y 新的视频.mp4
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
    
            command.add("-i");
            command.add(videoInputPath);
    
            command.add("-i");
            command.add(mp3InputPath);
    
            command.add("-t");
            command.add(String.valueOf(seconds));
    
            command.add("-y");
            command.add(videoOutputPath);
    
    //      for (String c : command) {
    //          System.out.print(c + " ");
    //      }
    
            ProcessBuilder builder = new ProcessBuilder(command);
            Process process = builder.start();
    
            InputStream errorStream = process.getErrorStream();
            InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
            BufferedReader br = new BufferedReader(inputStreamReader);
    
            String line = "";
            while ( (line = br.readLine()) != null ) {
            }
    
            if (br != null) {
                br.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (errorStream != null) {
                errorStream.close();
            }
    
        }
    
        public static void main(String[] args) {
            MergeVideoMp3 ffmpeg = new MergeVideoMp3("D:\Program Files\ffmpeg\bin\ffmpeg.exe");
            try {
                ffmpeg.convertor("D:\Program Files\ffmpeg\bin\shanzhu.mp4", "D:\Program Files\ffmpeg\bin\music.mp3", 7.1, "D:\Program Files\ffmpeg\bin\合并音乐和视频.avi");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    
    

    开发功能

    视频上传后通过java调用ffmpge.exe完成音乐和视频的合并,并将视频信息保存在数据库中。

    • 视频service开发
      VideoService
    package com.idig8.service;
    
    import com.idig8.pojo.Videos;
    
    public interface VideoService {
    
    
        /**
         * 保存视频信息
         * @param Id
         * @return
         */
        public void saveVideo(Videos video);
    }
    
    
    

    VideoServiceImpl

    package com.idig8.service.Impl;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.idig8.mapper.BgmMapper;
    import com.idig8.pojo.Bgm;
    import com.idig8.service.BgmService;
    
    @Service
    public class BgmServiceImpl implements BgmService {
    
        @Autowired
        private BgmMapper bgmMapper;
    
    
        @Transactional(propagation =Propagation.SUPPORTS)
        @Override
        public List<Bgm> queryBgmList(){
    
            return bgmMapper.selectAll();
        }
    
        @Transactional(propagation =Propagation.SUPPORTS)
        @Override
        public Bgm queryBgmById(String Id){
    
            return bgmMapper.selectByPrimaryKey(Id);
        }
    
    }
    

    BgmService

    package com.idig8.service;
    
    import java.util.List;
    
    import com.idig8.pojo.Bgm;
    
    public interface BgmService {
    
        /**
         * 获取所有的Bgm列表
         * @return
         */
        public List<Bgm> queryBgmList();
    
        /**
         * 通过bgmId获取Bgm对象
         * @param Id
         * @return
         */
        public Bgm queryBgmById(String Id);
    }
    
    
    

    BgmServiceImpl

    package com.idig8.service.Impl;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.idig8.mapper.BgmMapper;
    import com.idig8.pojo.Bgm;
    import com.idig8.service.BgmService;
    
    @Service
    public class BgmServiceImpl implements BgmService {
    
        @Autowired
        private BgmMapper bgmMapper;
    
    
        @Transactional(propagation =Propagation.SUPPORTS)
        @Override
        public List<Bgm> queryBgmList(){
    
            return bgmMapper.selectAll();
        }
    
        @Transactional(propagation =Propagation.SUPPORTS)
        @Override
        public Bgm queryBgmById(String Id){
    
            return bgmMapper.selectByPrimaryKey(Id);
        }
    
    }
    
    

    VideoController

    package com.idig8.controller;
    
    import java.io.File;
    import java.util.Date;
    import java.util.UUID;
    
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.idig8.pojo.Bgm;
    import com.idig8.pojo.Videos;
    import com.idig8.service.BgmService;
    import com.idig8.service.VideoService;
    import com.idig8.utils.JSONResult;
    import com.idig8.utils.MergeVideoMp3;
    import com.idig8.utils.enums.VideoStatusEnum;
    import com.idig8.utils.file.FileUtil;
    
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import io.swagger.annotations.ApiParam;
    
    
    @RestController
    @Api(value="视频相关业务的接口", tags= {"视频相关业务的controller"})
    @RequestMapping("/video")
    public class VideoController extends BasicController {
    
        @Autowired
        private BgmService bgmService;
    
        @Autowired
        private VideoService videosService;
    
        @Value("${server.file.path}")
        private String fileSpace;
    
        @Value("${server.ffmpeg.path}")
        private String ffmpegexe;
    
    
        @ApiOperation(value="上传视频", notes="上传视频的接口")
        @ApiImplicitParams({
            @ApiImplicitParam(name="userId", value="用户id", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="bgmId", value="背景音乐id", required=false, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoSeconds", value="背景音乐播放长度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoWidth", value="视频宽度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoHeight", value="视频高度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="desc", value="视频描述", required=false, 
                    dataType="String", paramType="form")
        })
        @PostMapping(value="/upload", headers="content-type=multipart/form-data")
        public JSONResult upload(String userId, 
                    String bgmId, double videoSeconds, 
                    int videoWidth, int videoHeight,
                    String desc,
                    @ApiParam(value="短视频", required=true)
                    MultipartFile file) throws Exception {
    
            if (StringUtils.isBlank(userId)) {
                return JSONResult.errorMsg("用户id不能为空...");
            }
            // 文件保存的命名空间
            String fileName = file.getOriginalFilename();
            // 保存到数据库中的相对路径
            String path = "";
            String videOutPath = "";
            try {
                 path = FileUtil.uploadFile(file.getBytes(), fileSpace, fileName);
                } catch (Exception e) {
                    e.getStackTrace();
                       return JSONResult.errorMsg(e.getMessage());
                }                
    
    
            if(StringUtils.isNotBlank(bgmId)){
                Bgm bgm = bgmService.queryBgmById(bgmId);
                String mp3BgmPath = fileSpace + bgm.getPath();
                MergeVideoMp3 mergeVideoMp3 = new MergeVideoMp3(ffmpegexe);
                String videOutPathName = UUID.randomUUID().toString()+".mp4";
                File targetFile = new File(fileSpace + userId);
                if (!targetFile.exists()) {
                    targetFile.mkdirs();
                }
                videOutPath = "/"+userId+"/"+videOutPathName;
                String videoInput = fileSpace +path;
                mergeVideoMp3.convertor(videoInput, mp3BgmPath, videoSeconds, fileSpace +videOutPath);
            }
    
    
            Videos videos = new Videos();
            videos.setAudioId(bgmId);
            videos.setCreateTime(new Date());
            videos.setVideoDesc(desc);
            videos.setId(UUID.randomUUID().toString());
            videos.setUserId(userId);
            videos.setVideoHeight(videoHeight);
            videos.setVideoWidth(videoWidth);
            videos.setVideoPath(videOutPath);
            videos.setStatus(VideoStatusEnum.SUCCESS.value);
            videosService.saveVideo(videos);
    
            return JSONResult.ok(path);
    
        }
    }
    

    PS:已经完成了视频的上传,并把相关的信息保存在数据库中。

  • 相关阅读:
    Spring Security Oauth2 认证(获取token/刷新token)流程
    Centos7安装配置Apache(httpd)+php+mysql+phpMyAdmin
    servlet 请求(Request)
    关于对连接数据库时出现1130-host “**” is not allowed to connect to this MySql/mariadb server 的错误解决方法
    在Spring中配置Hibernate和单独配置Hibernate的区别
    新手学Struts2的几个小注意事项
    Oracle 11g 发行版2 新安装后关于登录的一些基本操作
    CentOS7下mariaDB和phpmyadmin的一些安装和配置问题
    Ubuntu的一些文件系统的操作(转自我自己的其他博客)
    jquery上传图片获取像素
  • 原文地址:https://www.cnblogs.com/sharpest/p/10310575.html
Copyright © 2011-2022 走看看