Changeset 834bcc3 in Klonkt for src/services/AudioTranscoder.js
- Timestamp:
- 06/23/2026 06:14:27 PM (3 months ago)
- Branches:
- main
- Children:
- d774679
- Parents:
- bb42dfb
- File:
-
- 1 edited
-
src/services/AudioTranscoder.js (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/AudioTranscoder.js
rbb42dfb r834bcc3 126 126 size: outStat.size, 127 127 mimeType: 'audio/mpeg', 128 durationSec, // hele seconden uit ffmpeg's codecData (null als onbekend)128 durationSec, // whole seconds from ffmpeg's codecData (null if unknown) 129 129 }; 130 130 … … 138 138 139 139 /** 140 * Herschrijf de ID3-tags van een BESTAANDE mp3 zonder her-encoden(`-c copy`).141 * Gebruikt bij het bewerken van track-metadata (titel/artiest/album/credit/licentie)142 * zodat de eigendomsinfo in het bestand zelf meereist bij een download.143 * ffmpeg kan niet in-place editen → schrijf naar tmp en hernoem atomisch terug.140 * Rewrite the ID3 tags of an EXISTING mp3 without re-encoding (`-c copy`). 141 * Used when editing track metadata (title/artist/album/credit/license) so that 142 * ownership info travels with the file on download. 143 * ffmpeg cannot edit in-place → write to tmp and atomically rename back. 144 144 */ 145 145 export async function retagMp3({ filePath, tags = {} }) { 146 146 if (!filePath) throw new Error('retagMp3: filePath required'); 147 await stat(filePath); // throws als 't bestand mist147 await stat(filePath); // throws if file is missing 148 148 const dir = path.dirname(filePath); 149 149 const base = path.basename(filePath, path.extname(filePath)); … … 152 152 await new Promise((resolve, reject) => { 153 153 const cmd = ffmpeg(filePath) 154 .audioCodec('copy') // geen her-encode → snel, geen kwaliteitsverlies154 .audioCodec('copy') // no re-encode → fast, no quality loss 155 155 .format('mp3') 156 156 .outputOptions('-id3v2_version', '3') … … 167 167 }); 168 168 const s = await stat(tmpPath); 169 if (s.size === 0) throw new Error('retag output is leeg');169 if (s.size === 0) throw new Error('retag output is empty'); 170 170 await rename(tmpPath, filePath); 171 171 return { filePath, size: s.size }; 172 172 } catch (err) { 173 try { await unlink(tmpPath); } catch { /* tmp bestaat mogelijk niet */ }173 try { await unlink(tmpPath); } catch { /* tmp may not exist */ } 174 174 throw err; 175 175 } … … 209 209 if (tags.artist) cmd.outputOptions('-metadata', `artist=${tags.artist}`); 210 210 if (tags.album) cmd.outputOptions('-metadata', `album=${tags.album}`); 211 if (tags.copyright) cmd.outputOptions('-metadata', `copyright=${tags.copyright}`); // ID3 TCOP — eigenaar/credit212 if (tags.comment) cmd.outputOptions('-metadata', `comment=${tags.comment}`); // ID3 COMM — licen tie211 if (tags.copyright) cmd.outputOptions('-metadata', `copyright=${tags.copyright}`); // ID3 TCOP — owner/credit 212 if (tags.comment) cmd.outputOptions('-metadata', `comment=${tags.comment}`); // ID3 COMM — license 213 213 214 214 cmd 215 // codecData g eeft de duur van de INPUT als "HH:MM:SS.xx" — zo bepalen we216 // de tracklengte automatisch zonder aparte ffprobe-binary.215 // codecData gives the INPUT duration as "HH:MM:SS.xx" — this lets us 216 // determine the track length automatically without a separate ffprobe binary. 217 217 .on('codecData', (data) => { durationSec = parseHmsToSeconds(data && data.duration); }) 218 218 .on('error', (err, stdout, stderr) => { … … 230 230 231 231 /** 232 * Parse een ffmpeg-duurstring "HH:MM:SS.xx" naar hele seconden. Geeft null bij233 * "N/A" of een onverwacht formaat.232 * Parse an ffmpeg duration string "HH:MM:SS.xx" to whole seconds. Returns null 233 * for "N/A" or an unexpected format. 234 234 */ 235 235 function parseHmsToSeconds(hms) { … … 242 242 243 243 /** 244 * Lees de duur (hele seconden) van een audiobestand ZONDER te transcoderen.245 * Start een ffmpeg-pass en leest enkel het codecData-event (duur), waarna we het246 * proces direct stoppen — snel en zonder aparte ffprobe-binary (ffmpeg-static247 * levert alleen ffmpeg). Bedoeld voor het backfill-script.244 * Read the duration (whole seconds) of an audio file WITHOUT transcoding. 245 * Starts an ffmpeg pass and reads only the codecData event (duration), then 246 * kills the process immediately — fast and without a separate ffprobe binary 247 * (ffmpeg-static ships only ffmpeg). Intended for the backfill script. 248 248 * @returns {Promise<number|null>} 249 249 */ … … 255 255 .on('codecData', (data) => { 256 256 durationSec = parseHmsToSeconds(data && data.duration); 257 try { cmd.kill('SIGKILL'); } catch { /* al klaar*/ }257 try { cmd.kill('SIGKILL'); } catch { /* already done */ } 258 258 finish(); 259 259 })
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)