diff --git a/tasks/transcribe-audio-file/TASK.md b/tasks/transcribe-audio-file/TASK.md index 71c0a08..f458c0b 100644 --- a/tasks/transcribe-audio-file/TASK.md +++ b/tasks/transcribe-audio-file/TASK.md @@ -15,6 +15,13 @@ inputs: - name: file_path description: Path to the audio file to transcribe. Auto-filled from the file browser. required: true + - name: output_dir + description: >- + Where to write the transcript. Absolute, or relative to the recording. Leave it out and the text + lands beside the recording, which is what a person clicking a file wants. A commander passes its own + directory so its results never land in the folder it watches. + required: false + hidden: true trigger: - type: file extensions: @@ -38,8 +45,8 @@ model call spent re-deriving what the plugin already returns. (`GET /api/user/settings`). 2. `POST` the file to `/api/transcribe/transcribe`. The plugin detects the language and transcribes faithfully in it — see `plugins/transcribe/skills/transcribe/SKILL.md` for the contract. -3. Write the transcription beside the audio file, same name, `.md`. Nothing is moved and nothing is - created around it. +3. Write the transcription as `.md` with the same base name — beside the recording by default, or into + `output_dir` when one is given. The directory is created if it does not exist. It overwrites a previous transcription of the same file, deliberately: a transcription is derived, and running it again means you wanted it again. diff --git a/tasks/transcribe-audio-file/index.ts b/tasks/transcribe-audio-file/index.ts index d63bc92..4a84db3 100644 --- a/tasks/transcribe-audio-file/index.ts +++ b/tasks/transcribe-audio-file/index.ts @@ -8,7 +8,8 @@ // only owns filing the result. import { existsSync } from 'node:fs'; -import { basename, dirname, join, extname } from 'node:path'; +import { mkdir } from 'node:fs/promises'; +import { basename, dirname, isAbsolute, join, extname } from 'node:path'; const filePath = process.env.INPUT_FILE_PATH; if (!filePath) { @@ -69,14 +70,31 @@ async function main() { const { text, detectedLanguage } = await transcribe(path, spokenLanguages); console.log(`Detected language: ${detectedLanguage}`); - // Beside the audio, same name, `.md`. Nothing is moved, nothing is created around it — this is the - // behaviour the file viewer's transcribe button had, and the one thing anybody wants from a - // transcription is the text next to the recording it came from. - // - // It overwrites a previous transcription of the same file deliberately: a transcription is derived, - // running it again means you wanted it again, and a `-2` beside it would only be a second file to - // read and choose between. - const transcriptPath = join(dirname(path), `${basename(path, extname(path))}.md`); + /* + Where the text goes. + + By default, beside the audio with the same name — the behaviour the file viewer's transcribe button + had, and what a person right-clicking a recording wants: the text turns up next to the thing it came + from. + + `output_dir` overrides it, and exists for callers that are not a person clicking a file. A commander + keeps its results in its OWN directory: writing them into the folder it watches would put its work in + the middle of its subject, where nobody asked for it and where its next pass has to tell the two + apart. Passing a destination is one input; making every such caller move the file afterwards is a + step in every loop, forever, and a window where the file is in the wrong place. + + Created if missing, so a caller does not have to make the directory first — the first run of a new + commander otherwise fails on a directory only this script knows the name of. + + Either way it overwrites a previous transcription of the same recording, deliberately: a + transcription is derived, running it again means you wanted it again, and a `-2` beside it would only + be a second file to read and choose between. + */ + const outputDir = process.env.INPUT_OUTPUT_DIR?.trim(); + const destDir = outputDir ? (isAbsolute(outputDir) ? outputDir : join(dirname(path), outputDir)) : dirname(path); + if (outputDir) await mkdir(destDir, { recursive: true }); + + const transcriptPath = join(destDir, `${basename(path, extname(path))}.md`); await Bun.write(transcriptPath, text); console.log(transcriptPath);