Python合并ts文件至mp4格式及解密教程详解
配置ffmpeg运行环境
ffmpeg官网



验证ffmpeg的环境变量配置

下载加密的ts的分片视频文件

如果index.m3u8
文件中存在#EXT-X-KEY
则表示当前文件是加密;反之则无。


合并所有ts分片的视频
ffmpeg -allowed_extensions ALL -i index.m3u8 -c copy new.mp4
|

java-示例代码
package com.ruoyi.manman; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List;
public class VideoDownloader {
// https://xx.xxx.com/index.m3u8 // https://xx.xxx.com/enc.key // https://xx.xxx.com/index0.ts
// 下载地址前缀URL private static final String PREFIX_URL = "https://xx.xxx.com/"; // 视频文件ts的前缀(完整示例:index1.ts,程序自动拼接`x.ts`,) private static final String BASE_URL = PREFIX_URL + "index"; // 视频文件的索引文件 private static final String INDEX_M3U8 = "index.m3u8"; // 视频文件解密key private static final String ENC_KEY = "enc.key"; // 分片ts视频文件下载目录 private static final String OUTPUT_DIR = "D:\\Env\\Tmp\\"; // 合并视频文件名 private static final String MERGED_FILE = "xxx.mp4";
public static void main(String[] args) {
VideoDownloader downloader = new VideoDownloader(); downloader.downloadAndMergeVideos();
}
public static void convertTsToMp4(String inputFile, String outputFile) { try {
// ffmpeg -allowed_extensions ALL -i index.m3u8 -c copy new.mp4 ProcessBuilder builder = new ProcessBuilder( "D:\\Env\\ffmpeg\\ffmpeg-7.0.2-essentials_build\\bin\\ffmpeg.exe", "-allowed_extensions", "ALL", "-i", inputFile, "-c", "copy", outputFile );
// 将错误输出合并到标准输出 builder.redirectErrorStream(true); Process process = builder.start();
// 读取输出信息 try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } }
// 等待转换完成 int exitCode = process.waitFor(); if (exitCode == 0) { System.out.println("视频转换成功!"); } else { System.out.println("视频转换失败,错误码:" + exitCode); }
} catch (IOException | InterruptedException e) { e.printStackTrace(); } }
public void downloadAndMergeVideos() { List<String> downloadedFiles = new ArrayList<>(); int index = 0; // 起始索引
// 创建下载目录 new File(OUTPUT_DIR).mkdirs();
// 下载所有分片 while (true) { String url = BASE_URL + index + ".ts"; String outputFile = OUTPUT_DIR + "index" + index + ".ts";
if (!downloadFile(url, outputFile)) { break; // 如果下载失败(状态码不是200),退出循环 }
downloadedFiles.add(outputFile); index++; }
// 下载视频索引及加密key downloadFile(PREFIX_URL+INDEX_M3U8, OUTPUT_DIR+INDEX_M3U8); downloadFile(PREFIX_URL+ENC_KEY, OUTPUT_DIR+ENC_KEY);
// 合并文件 String inputFile = OUTPUT_DIR + INDEX_M3U8; String outputFile = OUTPUT_DIR + MERGED_FILE; convertTsToMp4(inputFile, outputFile);
// 清理临时文件 cleanupTempFiles(downloadedFiles); }
private boolean downloadFile(String urlStr, String outputFile) { try { URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET");
if (conn.getResponseCode() != 200) { return false; }
try (InputStream in = conn.getInputStream(); FileOutputStream out = new FileOutputStream(outputFile)) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } } return true; } catch (IOException e) { e.printStackTrace(); return false; } }
private void cleanupTempFiles(List<String> files) { for (String file : files) { new File(file).delete(); } }
}
|