Skip to content

Commit

Permalink
fix broken black/silence detection #1705
Browse files Browse the repository at this point in the history
  • Loading branch information
mifi committed Sep 6, 2023
1 parent 1acf72f commit 91ceef3
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 37 deletions.
36 changes: 35 additions & 1 deletion public/ffmpeg.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,39 @@ async function detectIntervals({ filePath, customArgs, onProgress, from, to, mat
return adjustSegmentsWithOffset({ segments, from });
}

const mapFilterOptions = (options) => Object.entries(options).map(([key, value]) => `${key}=${value}`).join(':');

async function blackDetect({ filePath, filterOptions, onProgress, from, to }) {
function matchLineTokens(line) {
const match = line.match(/^[blackdetect\s*@\s*0x[0-9a-f]+] black_start:([\d\\.]+) black_end:([\d\\.]+) black_duration:[\d\\.]+/);
if (!match) return {};
return {
start: parseFloat(match[1]),
end: parseFloat(match[2]),
};
}
const customArgs = ['-vf', `blackdetect=${mapFilterOptions(filterOptions)}`, '-an'];
return detectIntervals({ filePath, onProgress, from, to, matchLineTokens, customArgs });
}

async function silenceDetect({ filePath, filterOptions, onProgress, from, to }) {
function matchLineTokens(line) {
const match = line.match(/^[silencedetect\s*@\s*0x[0-9a-f]+] silence_end: ([\d\\.]+)[|\s]+silence_duration: ([\d\\.]+)/);
if (!match) return {};
const end = parseFloat(match[1]);
const silenceDuration = parseFloat(match[2]);
if (Number.isNaN(end) || Number.isNaN(silenceDuration)) return {};
const start = end - silenceDuration;
if (start < 0 || end <= 0 || start >= end) return {};
return {
start,
end,
};
}
const customArgs = ['-af', `silencedetect=${mapFilterOptions(filterOptions)}`, '-vn'];
return detectIntervals({ filePath, onProgress, from, to, matchLineTokens, customArgs });
}

function getFffmpegJpegQuality(quality) {
// Normal range for JPEG is 2-31 with 31 being the worst quality.
const qMin = 2;
Expand Down Expand Up @@ -522,12 +555,13 @@ module.exports = {
renderWaveformPng,
mapTimesToSegments,
detectSceneChanges,
detectIntervals,
captureFrames,
captureFrame,
getFfCommandLine,
html5ify,
getDuration,
getOneRawFrame,
encodeLiveRawStream,
blackDetect,
silenceDetect,
};
36 changes: 1 addition & 35 deletions src/ffmpeg.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const { pathExists } = window.require('fs-extra');

const remote = window.require('@electron/remote');

const { renderWaveformPng, mapTimesToSegments, detectSceneChanges, detectIntervals, captureFrames, captureFrame, getFfCommandLine, runFfmpegConcat, runFfmpegWithProgress, html5ify, getDuration, abortFfmpegs, runFfmpeg, runFfprobe, getFfmpegPath, setCustomFfPath } = remote.require('./ffmpeg');
const { renderWaveformPng, mapTimesToSegments, detectSceneChanges, captureFrames, captureFrame, getFfCommandLine, runFfmpegConcat, runFfmpegWithProgress, html5ify, getDuration, abortFfmpegs, runFfmpeg, runFfprobe, getFfmpegPath, setCustomFfPath } = remote.require('./ffmpeg');


export { renderWaveformPng, mapTimesToSegments, detectSceneChanges, captureFrames, captureFrame, getFfCommandLine, runFfmpegConcat, runFfmpegWithProgress, html5ify, getDuration, abortFfmpegs, runFfprobe, getFfmpegPath, setCustomFfPath };
Expand Down Expand Up @@ -483,40 +483,6 @@ export async function renderThumbnails({ filePath, from, duration, onThumbnail }
}, { concurrency: 2 });
}


const mapFilterOptions = (options) => Object.entries(options).map(([key, value]) => `${key}=${value}`).join(':');

export async function blackDetect({ filePath, filterOptions, onProgress, from, to }) {
function matchLineTokens(line) {
const match = line.match(/^[blackdetect\s*@\s*0x[0-9a-f]+] black_start:([\d\\.]+) black_end:([\d\\.]+) black_duration:[\d\\.]+/);
if (!match) return {};
return {
start: parseFloat(match[1]),
end: parseFloat(match[2]),
};
}
const customArgs = ['-vf', `blackdetect=${mapFilterOptions(filterOptions)}`, '-an'];
return detectIntervals({ filePath, onProgress, from, to, matchLineTokens, customArgs });
}

export async function silenceDetect({ filePath, filterOptions, onProgress, from, to }) {
function matchLineTokens(line) {
const match = line.match(/^[silencedetect\s*@\s*0x[0-9a-f]+] silence_end: ([\d\\.]+)[|\s]+silence_duration: ([\d\\.]+)/);
if (!match) return {};
const end = parseFloat(match[1]);
const silenceDuration = parseFloat(match[2]);
if (Number.isNaN(end) || Number.isNaN(silenceDuration)) return {};
const start = end - silenceDuration;
if (start < 0 || end <= 0 || start >= end) return {};
return {
start,
end,
};
}
const customArgs = ['-af', `silencedetect=${mapFilterOptions(filterOptions)}`, '-vn'];
return detectIntervals({ filePath, onProgress, from, to, matchLineTokens, customArgs });
}

export async function extractWaveform({ filePath, outPath }) {
const numSegs = 10;
const duration = 60 * 60;
Expand Down
6 changes: 5 additions & 1 deletion src/hooks/useSegments.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import pMap from 'p-map';

import sortBy from 'lodash/sortBy';

import { blackDetect, silenceDetect, detectSceneChanges as ffmpegDetectSceneChanges, readFrames, mapTimesToSegments, findKeyframeNearTime } from '../ffmpeg';
import { detectSceneChanges as ffmpegDetectSceneChanges, readFrames, mapTimesToSegments, findKeyframeNearTime } from '../ffmpeg';
import { handleError, shuffleArray } from '../util';
import { errorToast } from '../swal';
import { showParametersDialog } from '../dialogs/parameters';
Expand All @@ -15,6 +15,10 @@ import { createSegment, findSegmentsAtCursor, sortSegments, invertSegments, getS
import * as ffmpegParameters from '../ffmpeg-parameters';
import { maxSegmentsAllowed } from '../util/constants';

const remote = window.require('@electron/remote');

const { blackDetect, silenceDetect } = remote.require('./ffmpeg');


export default ({
filePath, workingRef, setWorking, setCutProgress, mainVideoStream,
Expand Down

0 comments on commit 91ceef3

Please sign in to comment.