11const fs = require ( 'fs' )
22const Mustache = require ( 'mustache' )
3- const { spawn } = require ( 'child_process' )
3+ const { spawn, exec } = require ( 'child_process' )
44const { v1 : uuidv1 } = require ( 'uuid' )
55const debug = require ( 'debug' ) ( 'botium-speech-processing-convert' )
66
7- const runconvert = ( cmdLine , outputFile , { inputBuffer , start , end } ) => {
7+ const _getSoxFileType = ( filename ) => {
88 return new Promise ( ( resolve , reject ) => {
9- const output = `${ process . env . BOTIUM_SPEECH_TMP_DIR || '/tmp' } /${ uuidv1 ( ) } _${ outputFile } `
10-
11- let cmdLineFull = Mustache . render ( cmdLine , { output } )
12- if ( start && end ) {
13- cmdLineFull = `${ cmdLineFull } trim ${ start } ${ end } `
14- } else if ( start && ! end ) {
15- cmdLineFull = `${ cmdLineFull } trim ${ start } `
16- } else if ( ! start && end ) {
17- cmdLineFull = `${ cmdLineFull } trim 0 ${ end } `
9+ exec ( `soxi -t ${ filename } ` , ( err , stdout , stderr ) => {
10+ if ( err ) return reject ( err )
11+ if ( stderr ) return reject ( stderr . trim ( ) )
12+ resolve ( stdout . trim ( ) )
13+ } )
14+ } )
15+ }
16+
17+ const _isMP3 = ( buf ) => {
18+ if ( ! buf || buf . length < 3 ) {
19+ return false
20+ }
21+ return ( buf [ 0 ] === 73 &&
22+ buf [ 1 ] === 68 &&
23+ buf [ 2 ] === 51 ) || (
24+ buf [ 0 ] === 255 &&
25+ ( buf [ 1 ] === 251 || buf [ 1 ] === 250 )
26+ )
27+ }
28+
29+ const runconvert = async ( cmdLine , outputName , { inputBuffer, start, end } ) => {
30+ const jobId = uuidv1 ( )
31+
32+ const writeInput = ! outputName || cmdLine . indexOf ( '{{{input}}}' ) >= 0 || cmdLine . indexOf ( '{{{inputtype}}}' ) >= 0
33+
34+ let input = null
35+ let inputtype = null
36+
37+ if ( writeInput ) {
38+ input = `${ process . env . BOTIUM_SPEECH_TMP_DIR || '/tmp' } /${ jobId } _input`
39+ try {
40+ fs . writeFileSync ( input , inputBuffer )
41+ } catch ( err ) {
42+ debug ( `conversion process input file ${ input } not writable: ${ err . message } ` )
43+ throw new Error ( 'conversion process input file not writable' )
44+ }
45+ if ( _isMP3 ( inputBuffer ) ) {
46+ inputtype = 'mp3'
47+ } else {
48+ try {
49+ inputtype = await _getSoxFileType ( input )
50+ debug ( `Identified input type: ${ inputtype } ` )
51+ } catch ( err ) {
52+ debug ( `identification of input file type ${ input } failed: ${ err . message } ` )
53+ throw new Error ( 'identification of input file type failed' )
54+ }
55+ }
56+ if ( ! outputName ) {
57+ outputName = `output.${ inputtype } `
1858 }
19- debug ( `cmdLineFull: ${ cmdLineFull } ` )
59+ }
60+ const output = `${ process . env . BOTIUM_SPEECH_TMP_DIR || '/tmp' } /${ jobId } _${ outputName } `
61+
62+ let cmdLineFull = Mustache . render ( cmdLine , { output, input, inputtype } )
63+ if ( start && end ) {
64+ cmdLineFull = `${ cmdLineFull } trim ${ start } ${ end } `
65+ } else if ( start && ! end ) {
66+ cmdLineFull = `${ cmdLineFull } trim ${ start } `
67+ } else if ( ! start && end ) {
68+ cmdLineFull = `${ cmdLineFull } trim 0 ${ end } `
69+ }
70+ debug ( `cmdLineFull: ${ cmdLineFull } ` )
71+
72+ return new Promise ( ( resolve , reject ) => {
2073 const childProcess = spawn ( '/bin/sh' , [ '-c' , cmdLineFull ] )
2174
2275 childProcess . once ( 'exit' , ( code , signal ) => {
@@ -25,13 +78,23 @@ const runconvert = (cmdLine, outputFile, { inputBuffer, start, end }) => {
2578 try {
2679 const outputBuffer = fs . readFileSync ( output )
2780 fs . unlinkSync ( output )
28- resolve ( outputBuffer )
81+ resolve ( {
82+ outputName,
83+ outputBuffer
84+ } )
2985 } catch ( err ) {
3086 reject ( new Error ( `conversion process output file ${ output } not readable: ${ err . message } ` ) )
3187 }
3288 } else {
3389 reject ( new Error ( `conversion process exited with code ${ code } , signal ${ signal } ` ) )
3490 }
91+ if ( input ) {
92+ try {
93+ fs . unlinkSync ( input )
94+ } catch ( err ) {
95+ debug ( `conversion process input file ${ input } not deleted: ${ err . message } ` )
96+ }
97+ }
3598 } )
3699 childProcess . once ( 'error' , ( err ) => {
37100 debug ( `conversion process failed: ${ err . message } ` )
@@ -50,7 +113,9 @@ const runconvert = (cmdLine, outputFile, { inputBuffer, start, end }) => {
50113 debug ( 'stderr ' + data )
51114 } )
52115
53- childProcess . stdin . write ( inputBuffer )
116+ if ( cmdLine . indexOf ( '{{{input}}}' ) < 0 ) {
117+ childProcess . stdin . write ( inputBuffer )
118+ }
54119 childProcess . stdin . end ( )
55120 } )
56121}
0 commit comments