修复seedking bugs

This commit is contained in:
CN-JS-HuiBai
2026-04-02 22:42:49 +08:00
parent a4bbacf1c7
commit 92e7a80a1e

View File

@@ -106,6 +106,49 @@ const createFfmpegOptions = (encoderName) => {
return options;
};
const parseFpsValue = (fpsText) => {
if (typeof fpsText !== 'string' || !fpsText.trim()) {
return 0;
}
if (fpsText.includes('/')) {
const [numeratorText, denominatorText] = fpsText.split('/');
const numerator = parseFloat(numeratorText);
const denominator = parseFloat(denominatorText);
if (Number.isFinite(numerator) && Number.isFinite(denominator) && denominator !== 0) {
return numerator / denominator;
}
return 0;
}
const numericValue = parseFloat(fpsText);
return Number.isFinite(numericValue) ? numericValue : 0;
};
const getSeekFriendlyOutputOptions = (encoderName, metadata) => {
const videoStream = (metadata?.streams || []).find((stream) => stream.codec_type === 'video') || {};
const parsedFps = parseFpsValue(videoStream.avg_frame_rate) || parseFpsValue(videoStream.r_frame_rate) || 24;
const normalizedFps = Math.min(Math.max(Math.round(parsedFps), 12), 60);
const gopSize = Math.max(24, normalizedFps * 2);
const options = [
'-movflags', 'frag_keyframe+empty_moov+default_base_moof+faststart',
'-frag_duration', '1000000',
'-min_frag_duration', '1000000',
'-g', gopSize.toString(),
'-keyint_min', gopSize.toString()
];
if (encoderName === 'libx264' || encoderName === 'libx265') {
options.push('-sc_threshold', '0', '-force_key_frames', 'expr:gte(t,n_forced*2)');
} else if (/_nvenc$/.test(encoderName)) {
options.push('-forced-idr', '1', '-force_key_frames', 'expr:gte(t,n_forced*2)');
} else if (/_qsv$/.test(encoderName)) {
options.push('-idr_interval', '1');
}
return options;
};
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);
@@ -430,8 +473,10 @@ app.get('/api/stream', async (req, res) => {
}
// Probe file for duration and broadcast to clients
let sourceMetadata = null;
try {
const metadata = await probeFile(tmpInputPath);
sourceMetadata = metadata;
const duration = metadata.format?.duration || 0;
progressMap[progressKey] = {
...(progressMap[progressKey] || {}),
@@ -449,7 +494,7 @@ app.get('/api/stream', async (req, res) => {
let ffmpegCommand = null;
const startStream = (encoderName) => {
const streamingOptions = createFfmpegOptions(encoderName).concat(['-movflags', 'frag_keyframe+empty_moov+faststart']);
const streamingOptions = createFfmpegOptions(encoderName).concat(getSeekFriendlyOutputOptions(encoderName, sourceMetadata));
ffmpegCommand = ffmpeg(tmpInputPath)
.videoCodec(encoderName)
.audioCodec('aac')