diff --git a/README.md b/README.md
index 6eb973c..958a9f9 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@ To properly test and run this project, you will need to prepare your environment
1. **Install Node.js & FFmpeg**:
- Ensure Node.js (v18+) is installed.
- Install **FFmpeg** on your system and make sure it is available in your PATH environment variable. The Node.js library `fluent-ffmpeg` requires it.
+ - If you plan to use Rockchip hardware encoding, make sure your FFmpeg build includes `h264_rkmpp` / `hevc_rkmpp` support and the device has the Rockchip MPP runtime available.
2. **AWS S3 / MinIO Configuration**:
- Modify the `.env` file (copy from `.env.example`).
diff --git a/public/index.html b/public/index.html
index 2809741..92b9b7e 100644
--- a/public/index.html
+++ b/public/index.html
@@ -68,6 +68,7 @@
NVIDIA
Intel
VAAPI
+ RKMPP
diff --git a/server.js b/server.js
index f5a5417..984b5a1 100644
--- a/server.js
+++ b/server.js
@@ -95,15 +95,17 @@ const broadcastWs = (key, payload) => {
};
const createFfmpegOptions = (encoderName) => {
- const options = ['-preset fast'];
+ const options = [];
if (encoderName === 'libx264' || encoderName === 'libx265') {
- options.push('-crf', '23', '-threads', '0');
+ options.push('-preset', 'fast', '-crf', '23', '-threads', '0');
} else if (/_nvenc$/.test(encoderName)) {
- options.push('-rc:v', 'vbr_hq', '-cq', '19');
+ options.push('-preset', 'fast', '-rc:v', 'vbr_hq', '-cq', '19');
} else if (/_qsv$/.test(encoderName)) {
- options.push('-global_quality', '23');
+ options.push('-preset', 'fast', '-global_quality', '23');
} else if (/_vaapi$/.test(encoderName)) {
options.push('-qp', '23');
+ } else if (/_rkmpp$/.test(encoderName)) {
+ options.push('-qp_init', '23', '-pix_fmt', 'nv12');
}
return options;
};
@@ -146,6 +148,8 @@ const getSeekFriendlyOutputOptions = (encoderName, metadata) => {
options.push('-forced-idr', '1', '-force_key_frames', 'expr:gte(t,n_forced*2)');
} else if (/_qsv$/.test(encoderName)) {
options.push('-idr_interval', '1');
+ } else if (/_rkmpp$/.test(encoderName)) {
+ options.push('-force_key_frames', 'expr:gte(t,n_forced*2)');
}
return options;
@@ -153,7 +157,7 @@ const getSeekFriendlyOutputOptions = (encoderName, metadata) => {
const shouldRetryWithSoftware = (message) => {
if (!message) return false;
- return /Cannot load libcuda\.so\.1|Could not open encoder before EOF|Error while opening encoder|Operation not permitted|Invalid argument/i.test(message);
+ return /Cannot load libcuda\.so\.1|Could not open encoder before EOF|Error while opening encoder|Operation not permitted|Invalid argument|mpp_create|rkmpp/i.test(message);
};
const probeFile = (filePath) => {
@@ -392,13 +396,14 @@ app.get('/api/stream', async (req, res) => {
}
const safeCodec = codec === 'h265' ? 'h265' : 'h264';
- const safeEncoder = ['nvidia', 'intel', 'vaapi', 'neon'].includes(encoder) ? encoder : 'software';
+ const safeEncoder = ['nvidia', 'intel', 'vaapi', 'rkmpp', 'neon'].includes(encoder) ? encoder : 'software';
const codecMap = {
software: { h264: 'libx264', h265: 'libx265' },
neon: { h264: 'libx264', h265: 'libx265' },
nvidia: { h264: 'h264_nvenc', h265: 'hevc_nvenc' },
intel: { h264: 'h264_qsv', h265: 'hevc_qsv' },
- vaapi: { h264: 'h264_vaapi', h265: 'hevc_vaapi' }
+ vaapi: { h264: 'h264_vaapi', h265: 'hevc_vaapi' },
+ rkmpp: { h264: 'h264_rkmpp', h265: 'hevc_rkmpp' }
};
const videoCodec = codecMap[safeEncoder][safeCodec];