Changeset 3e86f1c in Klonkt for src/services
- Timestamp:
- 06/15/2026 03:23:29 AM (3 months ago)
- Branches:
- main
- Children:
- 7f46817d
- Parents:
- 4c9f29a
- File:
-
- 1 edited
-
src/services/AudioTranscoder.js (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/AudioTranscoder.js
r4c9f29a r3e86f1c 90 90 const tmpPath = path.join(outputDir, `${outputBaseName}.transcoding-${process.pid}.mp3`); 91 91 92 let durationSec = null; 92 93 try { 93 await runFfmpeg({ inputPath, tmpPath, tags }); 94 const r = await runFfmpeg({ inputPath, tmpPath, tags }); 95 durationSec = r && r.durationSec != null ? r.durationSec : null; 94 96 95 97 // Verify the output is not zero bytes — ffmpeg sometimes "succeeds" but … … 124 126 size: outStat.size, 125 127 mimeType: 'audio/mpeg', 128 durationSec, // hele seconden uit ffmpeg's codecData (null als onbekend) 126 129 }; 127 130 … … 140 143 function runFfmpeg({ inputPath, tmpPath, tags }) { 141 144 return new Promise((resolve, reject) => { 145 let durationSec = null; 142 146 const cmd = ffmpeg(inputPath) 143 147 .audioCodec('libmp3lame') … … 168 172 169 173 cmd 174 // codecData geeft de duur van de INPUT als "HH:MM:SS.xx" — zo bepalen we 175 // de tracklengte automatisch zonder aparte ffprobe-binary. 176 .on('codecData', (data) => { durationSec = parseHmsToSeconds(data && data.duration); }) 170 177 .on('error', (err, stdout, stderr) => { 171 178 // ffmpeg's stderr is the most useful diagnostic. fluent-ffmpeg's … … 176 183 reject(new Error(`Transcode failed: ${reason}${tail ? '\n' + tail : ''}`)); 177 184 }) 178 .on('end', () => resolve( ))185 .on('end', () => resolve({ durationSec })) 179 186 .save(tmpPath); 180 187 }); 181 188 } 182 189 183 export default { transcodeToMp3 }; 190 /** 191 * Parse een ffmpeg-duurstring "HH:MM:SS.xx" naar hele seconden. Geeft null bij 192 * "N/A" of een onverwacht formaat. 193 */ 194 function parseHmsToSeconds(hms) { 195 if (!hms || typeof hms !== 'string') return null; 196 const m = hms.match(/^(\d+):(\d{2}):(\d{2})(?:\.(\d+))?$/); 197 if (!m) return null; 198 const sec = (+m[1]) * 3600 + (+m[2]) * 60 + (+m[3]) + (m[4] ? Number('0.' + m[4]) : 0); 199 return Number.isFinite(sec) ? Math.round(sec) : null; 200 } 201 202 /** 203 * Lees de duur (hele seconden) van een audiobestand ZONDER te transcoderen. 204 * Start een ffmpeg-pass en leest enkel het codecData-event (duur), waarna we het 205 * proces direct stoppen — snel en zonder aparte ffprobe-binary (ffmpeg-static 206 * levert alleen ffmpeg). Bedoeld voor het backfill-script. 207 * @returns {Promise<number|null>} 208 */ 209 export function probeDuration(filePath) { 210 return new Promise((resolve) => { 211 let durationSec = null, done = false; 212 const finish = () => { if (!done) { done = true; resolve(durationSec); } }; 213 const cmd = ffmpeg(filePath) 214 .on('codecData', (data) => { 215 durationSec = parseHmsToSeconds(data && data.duration); 216 try { cmd.kill('SIGKILL'); } catch { /* al klaar */ } 217 finish(); 218 }) 219 .on('error', finish) 220 .on('end', finish) 221 .format('null') 222 .save(process.platform === 'win32' ? 'NUL' : '/dev/null'); 223 }); 224 } 225 226 export default { transcodeToMp3, probeDuration };
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)