// Name: Trim Video Head/Tail // Description: Select a video file and export a new one with the first 9s and last 5s removed. // Author: thoncs // GitHub: thoncs import "@johnlindquist/kit" const HEAD_TRIM = 9 const TAIL_TRIM = 5 // Ensure ffmpeg/ffprobe are available if (!which("ffmpeg") || !which("ffprobe")) { await div(md(`# Missing ffmpeg/ffprobe Please install ffmpeg (which includes ffprobe) and try again. - macOS: brew install ffmpeg - Windows: winget install Gyan.FFmpeg or choco install ffmpeg - Linux: sudo apt-get install ffmpeg `)) exit(1) } // Pick input video (use Finder selection if available) let sel = await getSelectedFile() let inputPath = "" if (sel) { inputPath = sel.split("\n").filter(Boolean)[0] } else { inputPath = await selectFile("Select a video file to trim") } if (!inputPath) exit(1) try { // Get duration in seconds (float) const probe = await $`ffprobe -v error -show_entries format=duration -of default=nokey=1:noprint_wrappers=1 ${inputPath}` const total = parseFloat(probe.stdout.trim()) const newDuration = total - (HEAD_TRIM + TAIL_TRIM) if (!isFinite(newDuration) || newDuration <= 0) { await div(md(`Total duration (${total.toFixed(2)}s) is too short to remove ${HEAD_TRIM + TAIL_TRIM}s.`)) exit(1) } const ext = path.extname(inputPath) const base = path.basename(inputPath, ext) const dir = path.dirname(inputPath) const outName = `${base}-trimmed-${Math.floor(Date.now() / 1000)}${ext}` const outputPath = path.join(dir, outName) // Perform trim: seek 9s from start, keep newDuration, stream copy await div({ html: md(`## Trimming Video - Input: ${path.basename(inputPath)} - Start at: ${HEAD_TRIM}s - Output duration: ${newDuration.toFixed(2)}s - Output: ${outName} `), onInit: async () => { await $`ffmpeg -y -ss ${HEAD_TRIM} -i ${inputPath} -t ${newDuration} -c copy ${outputPath}` submit("done") }, }) await revealFile(outputPath) } catch (err) { await div(md(`Error:\n\`\`\`\n${String(err)}\n\`\`\``)) exit(1) }// Name: Trim Video (Remove Start/End) // Description: Select a video file and export a version without the first 9s and last 4s. // Author: thoncs // GitHub: thoncs import "@johnlindquist/kit" const START_TRIM_SECONDS = 9 const END_TRIM_SECONDS = 4 let inputPath: string = await getSelectedFile() if (!inputPath) { inputPath = await selectFile("Choose a video file to trim") } if (!inputPath) exit() // Handle multiple selections from getSelectedFile (newline-separated) if (inputPath.includes("\n")) inputPath = inputPath.split("\n").filter(Boolean)[0] // Ensure file exists const exists = await pathExists(inputPath) if (!exists) { await notify({ title: "Trim Video", body: "Selected file not found." }) exit() } // Probe duration let durationSec = 0 try { const { stdout } = await $`ffprobe -v error -show_entries format=duration -of default=nk=1:nw=1 ${inputPath}` durationSec = parseFloat(String(stdout).trim()) } catch (e: any) { await notify({ title: "Trim Video", body: "ffprobe not found or failed. Please install ffmpeg." }) exit() } const outputDuration = durationSec - START_TRIM_SECONDS - END_TRIM_SECONDS if (isNaN(outputDuration) || outputDuration <= 0) { await notify({ title: "Trim Video", body: "Video is too short to trim by requested amounts." }) exit() } // Build output path const { dir, name, ext } = path.parse(inputPath) const outputPath = path.join(dir, `${name}-trimmed${ext}`) // Run ffmpeg trim try { // Stream copy for speed; may be keyframe-accurate. Adjust as needed. await $`ffmpeg -y -ss ${START_TRIM_SECONDS} -t ${outputDuration.toFixed(3)} -i ${inputPath} -c copy ${outputPath}` await notify({ title: "Trim Video", body: "Export complete." }) await revealFile(outputPath) } catch (e: any) { await notify({ title: "Trim Video", body: "ffmpeg failed. Ensure ffmpeg is installed and try again." }) exit() }