-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Open
Labels
Description
It works fine when I convert mp4-format-video file to m3u8 with encryption,but I try a avi video file,it occurs this problem:
org.bytedeco.javacv.FFmpegFrameRecorder$Exception: avcodec_find_encoder() error: Video codec not found. (For more details, make sure FFmpegLogCallback.set() has been called.)
at org.bytedeco.javacv.FFmpegFrameRecorder.startUnsafe(FFmpegFrameRecorder.java:537)
at org.bytedeco.javacv.FFmpegFrameRecorder.start(FFmpegFrameRecorder.java:437)
at org.bytedeco.javacv.FFmpegFrameRecorder.start(FFmpegFrameRecorder.java:432)
at com.zzhua.controller.HlsEncryptConverter.convertToEncryptedHls(HlsEncryptConverter.java:65)
at com.zzhua.controller.HlsEncryptConverter.main(HlsEncryptConverter.java:120)
following dependencies:
javacv.version => 1.5.9
ffmpeg-platform => 6.0-1.5.9
import org.bytedeco.ffmpeg.avcodec.AVPacket;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Base64;
public class HlsEncryptConverter {
public static void convertToEncryptedHls(String inputPath, String outputDir, String hlsBaseUrl) throws Exception {
// 生成随机密钥(16 bytes for AES-128)
byte[] key = new byte[16];
new SecureRandom().nextBytes(key);
String keyHex = bytesToHex(key);
// 生成IV(可选)
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
String ivHex = bytesToHex(iv);
// 保存密钥到文件
String keyFileName = "encryption.key";
saveKeyFile(outputDir + File.separator + keyFileName, key);
FFmpegLogCallback.set();
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath);
grabber.start();
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
outputDir + File.separator + "output.m3u8",
grabber.getImageWidth(),
grabber.getImageHeight(),
grabber.getAudioChannels()
);
// 通用HLS配置
recorder.setFormat("hls");
recorder.setOption("hls_time", "10"); // 每个TS分片10秒
recorder.setOption("hls_list_size", "0"); // 无限播放列表
recorder.setOption("hls_segment_type", "mpegts");
recorder.setOption("hls_key_info_file", generateKeyInfoFile(outputDir, keyFileName, ivHex, hlsBaseUrl));
recorder.setOption("hls_flags", "independent_segments");
// 视频编码配置(兼容性配置)
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setVideoOption("preset", "medium");
recorder.setVideoBitrate(grabber.getVideoBitrate());
recorder.setVideoOption("tune", "film");
// 音频编码配置
recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
recorder.setAudioBitrate(grabber.getAudioBitrate());
recorder.setSampleRate(grabber.getSampleRate());
// 强制使用PTS作为时间戳
// recorder.setOption("use_wallclock_as_timestamps", "1");
recorder.start(grabber.getFormatContext());
AVPacket packet;
while ((packet = grabber.grabPacket()) != null) {
try {
recorder.recordPacket(packet);
} catch (FrameRecorder.Exception e) {
e.printStackTrace();
}
}
recorder.setTimestamp(grabber.getTimestamp());
recorder.stop();
recorder.release();
grabber.stop();
grabber.release();
recorder.close();
grabber.close();
}
private static String generateKeyInfoFile(String outputDir, String keyFileName, String iv, String baseUrl) throws IOException {
String keyInfoPath = outputDir + File.separator + "enc.keyinfo";
String keyUrl = baseUrl + keyFileName;
try (FileOutputStream fos = new FileOutputStream(keyInfoPath)) {
String content = keyUrl + "\n" + outputDir + File.separator + keyFileName + "\n" + iv;
fos.write(content.getBytes());
}
return keyInfoPath;
}
private static void saveKeyFile(String path, byte[] key) throws IOException {
try (FileOutputStream fos = new FileOutputStream(path)) {
fos.write(key);
}
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static void main(String[] args) {
try {
/*
// success case
String input = "D:\\temp\\test2\\test2.mp4";
String outputDir = "D:\\temp\\test2";
String baseUrl = "https://your-cdn.com/";
*/
// fail case
String input = "D:\\temp\\test1\\test1.avi";
String outputDir = "D:\\temp\\test1";
String baseUrl = "https://your-cdn.com/";
new File(outputDir).mkdirs();
convertToEncryptedHls(input, outputDir, baseUrl);
System.out.println("转换完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}