傻瓜式JAVA|傻瓜式JAVA MP4加密转码M3u8 并获取视频大小,长度

=======开头重要绿色链接,不看后悔,和下面关联==========
JAVA无需本地下载Ffmpeg,实现FfmpegCMD
本文不需要本地下载Ffmpeg,只需引入maven依赖即可
1、添加maven依赖

ws.schild jave-all-deps 3.3.1 ws.schild jave-core 3.3.1 ws.schild jave-nativebin-win64 3.3.1

2、编写代码
package com.gxw.util; import com.alibaba.fastjson.JSON; import ws.schild.jave.MultimediaObject; import ws.schild.jave.info.MultimediaInfo; import java.io.*; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.channels.FileChannel; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @Description:(MP4 转码 HLS m3u8 AES128 加密) * @author: GuoXiangWen * @date:2022年04月16日 上午08:08:08 */ public class EncodeVideoUtils { private static String PREIX = "gxwAwdlpgyn"; //加密文件路径,如:enc.key、enc.keyinfo、m3u8文件、ts文件等 private static String ENC_DIRECTORY = "D:/test-ffmpeg/"+PREIX; //enc.key地址 private static String ENC_KEY_FILE_PATH = null; //enc.keyinfo地址 private static String ENC_KEY_INFO_FILE_PATH = null; //密钥http地址 private static String ENC_HTTP_PATH = "http://127.0.0.1:8848/Student"; //执行成功0,失败1 private static int CODE_SUCCESS = 0; private static int CODE_FAIL = 1; //$encInfoPath、$encPath是需要替换的ENC_DIRECTORY文件路径 private static String cmd_enc = " -y -i {videoPath} -hls_time 12 -hls_key_info_file $encInfoPath -hls_playlist_type vod -hls_segment_filename $encPath\\{tsName}_%3d.ts $encPath\\{saveM3u8Name} "; public static void main(String[] args) { //视频路径 String videoPath = "D:/test-ffmpeg/test.mp4"; System.out.println(JSON.toJSONString(encodeVideo(videoPath, "test", "1"))); }/** * 第一步:创建enc.keyinfo文件 ** 第二步:HLS m3u8 AES128 加密 * @param videoPath 视频路径 * @param videoType 视频所属类型, * @param index 视频角标,传来递增的 * @return */ public synchronized static Map encodeVideo(String videoPath, String videoType, String index) { String videoTypeBP = videoType; String mp4Name = videoPath.substring(videoPath.lastIndexOf('/') + 1, videoPath.lastIndexOf(".mp4")); String saveM3u8Name = PREIX + RandomUtils.generateRandomString(32); //设置tsName cmd_enc = cmd_enc.replace("{tsName}", saveM3u8Name); //设置视频地址 cmd_enc = cmd_enc.replace("{videoPath}", videoPath); //设置视频保存名称地址cmd_enc = cmd_enc.replace("{saveM3u8Name}", saveM3u8Name + ".m3u8"); if(videoType.equals("") || videoType == null){ videoType = ""; }else { videoType = "/" + Md5Utils.md5Password(videoType, 8); } ENC_DIRECTORY = ENC_DIRECTORY + videoType + "/" + index; ENC_KEY_FILE_PATH = ENC_DIRECTORY + "/" + saveM3u8Name + ".key"; ENC_KEY_INFO_FILE_PATH = ENC_DIRECTORY + "/" + saveM3u8Name + ".keyinfo"; ENC_HTTP_PATH = ENC_HTTP_PATH + "/" + PREIX + videoType + "/" + index + "/" + saveM3u8Name + ".key"; // 先创建两个活动线程的线程池 ExecutorService executor = Executors.newFixedThreadPool(10); //异步执行 //第一步:创建enc.keyinfo文件等 CompletableFuture completableFutureTask = CompletableFuture.supplyAsync(() ->{//保存加密视频目录enc File encFilePathDir = new File(ENC_DIRECTORY); if (!encFilePathDir.exists()) {// 判断目录是否存在 encFilePathDir.mkdirs(); }//写入文件内容enc.key BufferedWriter bwkey = null; //写入文件内容enc.keyinfo BufferedWriter bwkeyInfo = null; try{//文件 File fileKey = new File(ENC_KEY_FILE_PATH); File fileKeyInfo = new File(ENC_KEY_INFO_FILE_PATH); //初始化存在删除 if(fileKey.exists()) { fileKey.delete(); } if(fileKeyInfo.exists()) { fileKeyInfo.delete(); } bwkey = new BufferedWriter(new FileWriter(fileKey)); bwkeyInfo = new BufferedWriter(new FileWriter(fileKeyInfo)); //写入key--自定义的AES128加密的密匙 bwkey.write("wgzsbbd_WGZS!5418!lAlA"); //写入keyInfo //密匙URL地址,可以对该URL鉴权 bwkeyInfo.write(ENC_HTTP_PATH); bwkeyInfo.newLine(); //全路径,绝对路径 bwkeyInfo.write(ENC_KEY_FILE_PATH); bwkey.flush(); bwkeyInfo.flush(); }catch(IOException e){ e.printStackTrace(); //恢复默认 ENC_KEY_INFO_FILE_PATH = null; } finally{ try { //一定要关闭文件 bwkey.close(); bwkeyInfo.close(); } catch (IOException e) { e.printStackTrace(); } } return ENC_KEY_INFO_FILE_PATH; }, executor).exceptionally(e -> { System.out.println(e); return "false"; }); //异步执行 //第二步:HLS m3u8 AES128 加密 CompletableFuture completableFutureTaskHls = completableFutureTask.thenApplyAsync((String encKeyInfoFilePath)->{ if(encKeyInfoFilePath == null || encKeyInfoFilePath.length() == 0) {return CODE_FAIL; } Integer codeTmp =cmdExecut(cmd_enc.replace("$encInfoPath", encKeyInfoFilePath).replace("$encPath", ENC_DIRECTORY)); if(CODE_SUCCESS != codeTmp) {return CODE_FAIL; } System.out.println("类型:"+videoTypeBP+" 视频:" + mp4Name + " 加密,成功!"); return codeTmp; }, executor).exceptionally(e -> { System.out.println(e); return null; }); //获取执行结果 //code=0表示正常 try { System.out.println(String.format("获取最终执行结果:%s", completableFutureTaskHls.get() == CODE_SUCCESS ? "成功!" : "失败!")); } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } //返回结果 Map resultMap = new HashMap<>(); //视频名称 resultMap.put("videoName", mp4Name); //视频大小 resultMap.put("videoSize", getVideoSize(new File(videoPath))); //视频时长 resultMap.put("videoTime", getVideoTime(videoPath)); //保存m3u8加密地址 resultMap.put("saveM3u8Path", ENC_DIRECTORY + "/" + saveM3u8Name + ".m3u8"); return resultMap; }/** * * @Description: (执行ffmpeg自定义命令) * @param: @param cmdStr * @param: @return * @return: Integer * @throws */ public static Integer cmdExecut(String cmdStr) { //code=0表示正常 Integer code= null; FfmpegCmd ffmpegCmd = new FfmpegCmd(); /** * 错误流 */ InputStream errorStream = null; try { ffmpegCmd.execute(false, true, cmdStr); errorStream = ffmpegCmd.getErrorStream(); //打印过程 int len = 0; while ((len=errorStream.read())!=-1){ System.out.print((char)len); }//code=0表示正常 code = ffmpegCmd.getProcessExitCode(); } catch (IOException e) { e.printStackTrace(); } finally { //关闭资源 ffmpegCmd.close(); } //返回 return code; }/** * 获取视频时长 * * @param FileUrl * @return */ public static String getVideoTime(String FileUrl) { File source = new File(FileUrl); String length = ""; try { MultimediaObject instance = new MultimediaObject(source); MultimediaInfo result = instance.getInfo(); long ls = result.getDuration() / 1000; Integer hour = (int) (ls / 3600); Integer minute = (int) (ls % 3600) / 60; Integer second = (int) (ls - hour * 3600 - minute * 60); String hr = hour.toString(); String mi = minute.toString(); String se = second.toString(); if (hr.length() < 2) { hr = "0" + hr; } if (mi.length() < 2) { mi = "0" + mi; } if (se.length() < 2) { se = "0" + se; } length = hr + ":" + mi + ":" + se; } catch (Exception e) { e.printStackTrace(); } return length; }/** * 获取视频大小 * * @param source * @return */ public static String getVideoSize(File source) { FileChannel fc = null; String size = ""; try { FileInputStream fis = new FileInputStream(source); fc = fis.getChannel(); BigDecimal fileSize = new BigDecimal(fc.size()); size = fileSize.divide(new BigDecimal(1024 * 1024), 2, RoundingMode.HALF_UP) + "MB"; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (null != fc) { try { fc.close(); } catch (IOException e) { e.printStackTrace(); } } } return size; }}

3、运行测试 【傻瓜式JAVA|傻瓜式JAVA MP4加密转码M3u8 并获取视频大小,长度】获得以下结果,即成功:
傻瓜式JAVA|傻瓜式JAVA MP4加密转码M3u8 并获取视频大小,长度
文章图片

    推荐阅读