最近项目需要将用户上传的视频如果不是MP4格式,需要全部转码为MP4格式的,这里我通过FFMPeg进行大文件视频转码的实现。

一、安装FFMPeg

首先我们需要在机器上安装FFMPeg用于我们的视频转码,传送门如下:

Centos7 安装FFMPEG

Ubuntu 安装FFMPEG及简单使用

二、视频转码实现

1、FileManagementHelper 视频转码类

package com.openailab.oascloud.file.common.helper;import com.openailab.oascloud.file.common.config.BootstrapConfig;
import com.openailab.oascloud.file.common.consts.BootstrapConst;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;/*** @description: 视频转码* @author: zhangzhixiang* @createDate: 2019/12/11* @version: 1.0*/
@Component
public class FileManagementHelper {private static final Logger LOG = LoggerFactory.getLogger(FileManagementHelper.class);@Autowiredprivate BootstrapConfig bootstrapConfig;/*** 文件转码** @param filePath* @return com.openailab.oascloud.common.model.ResponseResult* @author zxzhang* @date 2019/12/10*/public int transcode(String filePath) {//1、获取文件名和后缀String ext = getExt(filePath);String fileDir = getFileDir(filePath);String fileName = getFileName(filePath);//2、删除同名文件File originFile = new File(fileDir + fileName + BootstrapConst.SPOT + ext);if (originFile.exists()){originFile.delete();}//3、视频转码LinkedList<String> ffmpegCmds = new LinkedList<>();ffmpegCmds.add("ffmpeg");ffmpegCmds.add("-i");ffmpegCmds.add(bootstrapConfig.getFileRoot() + filePath);ffmpegCmds.add("-c:v");ffmpegCmds.add("libx264");ffmpegCmds.add("-strict");ffmpegCmds.add("-2");ffmpegCmds.add(bootstrapConfig.getFileRoot() + fileDir + BootstrapConst.PATH_SEPARATOR + fileName + ".mp4");ProcessBuilder builder = new ProcessBuilder();builder.command(ffmpegCmds);Process ffmpeg = null;try {ffmpeg = builder.start();} catch (IOException e) {e.printStackTrace();}String cmdStr = Arrays.toString(ffmpegCmds.toArray()).replace(",", "");LOG.info("---开始执行FFmpeg指令:--- 执行线程名:" + builder.toString());LOG.info("---已执行的FFmepg命令:---" + cmdStr);// 取出输出流和错误流的信息// 注意:必须要取出ffmpeg在执行命令过程中产生的输出信息,如果不取的话当输出流信息填满jvm存储输出留信息的缓冲区时,线程就回阻塞住PrintStream errorStream = new PrintStream(ffmpeg.getErrorStream());PrintStream inputStream = new PrintStream(ffmpeg.getInputStream());errorStream.start();inputStream.start();// 等待ffmpeg命令执行完int exit = 0;try {exit = ffmpeg.waitFor();} catch (InterruptedException e) {e.printStackTrace();}LOG.info("---执行结果:---" + (exit == 0 ? "【成功】" : "【失败】"));if (exit == 0) {originFile = new File(filePath);if(originFile.exists()){originFile.delete();}}return exit;}/*** 获取文件后缀** @param fileName* @return java.lang.String* @author zxzhang* @date 2019/12/10*/public String getExt(String fileName) {return fileName.substring(fileName.lastIndexOf(".") + 1);}/*** 获取文件所在目录** @param filePath* @return java.lang.String* @author zxzhang* @date 2019/12/10*/public String getFileDir(String filePath) {return filePath.substring(0, filePath.lastIndexOf(BootstrapConst.PATH_SEPARATOR));}/*** 获取文件名** @param filePath* @return java.lang.String* @author zxzhang* @date 2019/12/10*/public String getFileName(String filePath) {return filePath.substring(filePath.lastIndexOf(BootstrapConst.PATH_SEPARATOR) + 1, filePath.lastIndexOf("."));}
}class PrintStream extends Thread {java.io.InputStream __is = null;public PrintStream(java.io.InputStream is) {__is = is;}@Overridepublic void run() {try {while (this != null) {int _ch = __is.read();if (_ch != -1) {System.out.print((char) _ch);} else {break;}}} catch (Exception e) {e.printStackTrace();}}
}

2、BootstrapConst类

package com.openailab.oascloud.file.common.consts;/*** @Classname: com.openailab.oascloud.security.common.consts.BootstrapConst* @Description: 简单常量定义* @Author: zxzhang* @Date: 2019/10/8*/
public class BootstrapConst {/*** 文件缓冲区大小*/public static final Integer INPUT_BUFFER_SIZE = 8192;/*** 文件分隔符*/public static final char PATH_SEPARATOR = '/';/*** 文件点*/public static final char SPOT = '.';/*** 常量一*/public static final Integer ONE = 1;/*** 成功*/public static final Integer SUCCESS = 1;/*** 失败*/public static final Integer FAIL = 0;/*** true*/public static final Boolean TRUE = true;/*** false*/public static final Boolean FALSE = false;
}

三、FFMPeg DockerFile实现

首先我们构建具有JDK1.8和FFMPeg环境的镜像

FROM jrottenberg/ffmpeg:centos
MAINTAINER oas.cloud
ADD jdk-8u231-linux-x64.tar.gz /usr/local/
ENV JAVA_HOME /usr/local/jdk1.8.0_231
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin
WORKDIR /usr/local/oas/

然后将上述文件构建出的镜像的tag打为我们自己的镜像仓库地址,改为 10.12.1.202:8088/oascloud/ffmpeg:v1.0,我们的应用程序就可以以上述镜像文件(10.12.1.202:8088/oascloud/ffmpeg:v1.0)为基础构建出新的应用程序镜像,应用程序的DockerFile如下:

FROM 10.12.1.202:8088/oascloud/ffmpeg:v1.0
MAINTAINER oas.cloud
ENV LC_ALL=zh_CN.utf8
ENV LANG=zh_CN.utf8
ENV LANGUAGE=zh_CN.utf8
RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
ARG JAR_FILE
COPY ${JAR_FILE} /usr/local/oas/
WORKDIR /usr/local/oas/

代码结构如下:

附上Kubernetes编排文件,deploy.yaml内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:name: openailab-data-file-managementnamespace: oas-tengine2devlabels:name: openailab-data-file-management
spec:replicas: 1selector:matchLabels:name: openailab-data-file-managementtemplate:metadata:labels:name: openailab-data-file-managementspec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: envoperator: Invalues:- tengine2devcontainers:- name: openailab-data-file-managementimage: 10.12.1.202:8088/tengine2/openailab-data-file-management:latestenv:- name: APOLLO_APP_IDvalue: 'tengine2-data-file-management'- name: APOLLO_EUREKA_URIvalue: 'http://10.98.100.95:8080/'- name: APOLLO_NAMESPACEvalue: 'application'- name: SPRING_EUREKA_URIvalue: 'http://10.111.176.222:8080/eureka/'volumeMounts:- name: openailab-data-file-managementmountPath: /usr/local/logs- name: filemountPath: /usr/local/oas/filecommand: ['sh','-c','java -server -Xms2048m -Xmx3072m -Djava.io.tmpdir=/var/tmp -Duser.timezone=Asia/Shanghai -jar openailab-data-file-management-*.jar --server.port=8080 --spring.profiles.active=remote']ports:- containerPort: 8080resources:requests:memory: 256Micpu: 150mlimits:memory: 2048Micpu: 300minitContainers:- name: init-apolloimage: busyboxcommand: ['sh', '-c']args:- echo Prepare to apollo initialize..;until nc -w 1 -z 10.98.100.95 8080;do echo Waiting for eureka initialization to complete..; sleep 10; done;echo Eureka is ready.;until nc -w 1 -z 10.98.100.95 8090;do echo Waiting for admin initialization to complete..; sleep 10; done;echo Admin is ready.;echo Apollo Initialization successful!;volumes:- name: openailab-data-file-managementhostPath:path: /usr/local/logs- name: filehostPath:path: /usr/local/oas/file

svc.yaml内容如下:

apiVersion: v1
kind: Service
metadata:name: openailab-data-file-managementnamespace: oas-tengine2devlabels:name: openailab-data-file-management
spec:type: NodePortports:- nodePort: 32318targetPort: 8080port: 8080protocol: TCPselector:name: openailab-data-file-management

然后我们就可以快快乐乐的通过Kubenetes编排文件的方式部署了。

注:如果只是通过Docker运行镜像(不建议),则需要修改DockerFile内容,修改后的DockerFile如下所示:

FROM 10.12.1.202:8088/oascloud/ffmpeg:v1.0
MAINTAINER oas.cloud
ENV LC_ALL=zh_CN.utf8
ENV LANG=zh_CN.utf8
ENV LANGUAGE=zh_CN.utf8
RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
ARG JAR_FILE
COPY ${JAR_FILE} /usr/local/oas/
WORKDIR /usr/local/oas/
CMD java -server -Xms2048m -Xmx3072m -Djava.io.tmpdir=/var/tmp -Duser.timezone=Asia/Shanghai -jar openailab-data-file-management-*.jar --server.port=32318
EXPOSE 32318

到此 SpringBoot 实现大文件视频转码(转码基于FFMPEG实现)介绍完成。

SpringBoot 实现大文件视频转码(转码基于FFMPEG实现)相关推荐

  1. vue上传大文件/视频前后端(java)代码

    vue上传大文件/视频前后端(java)代码 一.上传组件 二.后端java代码 注意: 一.上传组件 <template><div><!-- 上传组件 -->&l ...

  2. uni-app上传大文件/视频失败详解

    大文件/视频上传失败可能会给你造成一个跨域的假象,仔细分析一下,如果小文件/视频可以上传成功.就说明不是跨域的问题,可以排除跨域.就可能是一下三个原因造成大文件/视频上传失败. 原因一: APP做了上 ...

  3. web大文件上传断点续传源码

    总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件 ...

  4. thinkphp6+webuploader实现大文件(视频)分片上传/本地保存或上传OSS

    thinkPHP6+webuploader分片上传大视频的解决方案: ①能解决视频太大,1G.2G直传服务器压力过大 ②部分追求完美的人不发接受直传,那只能分片上传 ③分片上传是我找到的比较合理的解决 ...

  5. android+高仿视频录制,高仿微信视频录制, 涂鸦水印添加, 基于 ffmpeg 视频编辑

    功能主要包含5点: 1.基于ffmpeg的视频拍摄及合成; 2.自定义拍摄按钮, 长按放大并且显示拍摄进度; 3.自定义view, 实现手绘涂鸦; 4.自定义可触摸旋转缩放位移的表情文字view; 5 ...

  6. 七牛云分片批量上传大文件视频

    原本用的element上传组件,结果发现大视频总是失败,还跑出outMemoryError :java heap space 内存溢出,排查:jvm内存默认256m,每次文件上传,用的是muiltip ...

  7. 【微信小程序分包上传大文件/视频】

    这不前两天来了个奇葩需求,我写的小视频平台人家要上传2个G以上的视频,一开始咋想都想不通怎么写,后来一下就茅厕顿开了属于是,话不多说直接上码! upload.js: var bytesPerPiece ...

  8. Web大文件(视频)上传解决方案

    前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对 Http 协议较模糊,故这次采用渐进的方式来学习文件上传的原理与实践. ...

  9. PHP上传大文件视频到阿里云oss分片上传

    下载阿里云oss的SDK composer require aliyuncs/oss-sdk-php 上传视频,我用的是分片上传,其实阿里云的文档已经写得很清楚了,不过这是当我把上传的功能写出来后才这 ...

最新文章

  1. 办公室“暧昧”的几种结局。
  2. PCA和白化练习之处理二维数据
  3. win32应用程序_不是有效的win32应用程序怎么解决
  4. 第一人称视角的一种解决方案
  5. 架构师接龙:百姓网潘晓良VS. 盛大许式伟
  6. 深度拷贝 java_Java深度拷贝方式和性能对比
  7. 医学影像设备学_医学影像技术考研可选的六大院校
  8. 【Linux】一步一步学Linux——VMware虚拟机三种网络模式详解(07)
  9. 如何在 IntelliJ IDEA 中整合 Maven、Tomcat 部署 Web 应用
  10. 瞧瞧 Fog Creek 软件公司办公环境
  11. 大龄程序员想转产品经理?3本书给你最靠谱的进阶攻略
  12. JAVA异常使用_每个人都曾用过、但未必都用得好
  13. 设计灵感|如何设计出简洁吸引人的字体海报?
  14. Unity 改变鼠标指针的方法
  15. 用低代码+BPM赋能知识文档管理系统
  16. C语言 打地鼠游戏 超级详解,各个函数与算法,设计思路与流程
  17. Android音视频点/直播模块开发
  18. pwn libc找偏移的在线网站
  19. Java小项目——客户的关系管理系统
  20. 电驴提示“该内容尚未提供权利证明,无法提供下载”之解决办法

热门文章

  1. 移动跨平台ReactNative开关组件Switch【15】
  2. TS 36.211 V12.0.0-上行(1)-时隙结构和物理资源
  3. 2.CUDA 编程手册中文版---编程模型
  4. 诺基亚联手迪信通 力推内置仙剑三版5230手机
  5. 水果店从哪里进货便宜,水果店都有哪些进货渠道
  6. 使用Asponse.cells生成图片如何去掉水印
  7. JDBC心得体会--总结
  8. 永久一键关闭QQ频道,不用重新安装
  9. [思语]_一花一世界,一树一菩提
  10. Mybatis 学习笔记