Skip to content

Instantly share code, notes, and snippets.

@tayiorbeii
Created October 5, 2022 17:07
Show Gist options
  • Select an option

  • Save tayiorbeii/15b7b80cff5bb40dc8c4cce46db9cc70 to your computer and use it in GitHub Desktop.

Select an option

Save tayiorbeii/15b7b80cff5bb40dc8c4cce46db9cc70 to your computer and use it in GitHub Desktop.
// Name: Split video on silences
// Description: detects video silences over a threshold length and deletes the silences
import "@johnlindquist/kit"
const replaceAll = await npm('just-replace-all')
const numbers = await npm('numbers-in-string')
const seconds = await npm('seconds-to-timestamp')
const chunk = await npm('chunk')
const leadingzero = await npm('leadingzero')
const MINUTES_OF_SILENCE = 4
const silenceInSeconds = MINUTES_OF_SILENCE * 60
/*
* Highlight the long video we are taking clips out of in Finder
*/
let longVideoFile = await getSelectedFile()
cd(path.dirname(longVideoFile))
/*
* Detect silences in long video file and parse timestamps
*/
let {stdout} = await exec(`ffmpeg -i "${longVideoFile}" -af silencedetect=noise=-50dB:d=${silenceInSeconds} -f null -`)
let detectedSilenceLines = stdout.split('\n').filter(x => x.includes('[silencedetect'))
let timestamps = chunk([0, ...detectedSilenceLines.map(x => x.split(': ')[1].split(' ')[0]).map(x => numbers(x)).flat()])
let cutsToMake = timestamps.map((time, index) => {
if (time[1] === undefined) {
return {
from: seconds(time[0]),
desc: `part${leadingzero(index+1, 2)}`
}
}
return {
from: seconds(time[0]),
to: seconds(time[1]),
desc: `part${leadingzero(index+1, 2)}`
}
})
let silentCutsToMake = cutsToMake.map((time, index) => {
if (index+1 == timeObj.length) {
return {}
}
return {
from: time['to'],
to: timeObj[index+1]['from'],
desc: `silent_part${leadingzero(index+1, 2)}`
}
}).slice(0,-1)
/*
* Split video clip, cutting out silences
*/
for (let cut of cutsToMake) {
let clipFileName = `${replaceAll(cut.desc, ' ', '_')}.mp4`
await exec(`ffmpeg -i "${longVideoFile}" -c copy -ss ${cut.from} ${cut.to ? `-to ${cut.to}`: ''} ${clipFileName}`)
}
/**
* Create silent videos just in case stuff happens
*/
for (let cut of silentCutsToMake) {
let clipFileName = `${replaceAll(cut.desc, ' ', '_')}.mp4`
await exec(`ffmpeg -i "${longVideoFile}" -c copy -ss ${cut.from} ${cut.to ? `-to ${cut.to}`: ''} ${clipFileName}`)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment