1+
2+ // nodejs child_process
3+ var childProcess = require ( 'child_process' ) ;
4+
5+ /**
6+ *
7+ * @returns {analyzerConstructor }
8+ */
9+ var analyzer = function analyzerConstructor ( ) {
10+
11+ } ;
12+
13+ /**
14+ *
15+ * get track data using ffprobe (channels, samplerate, ...)
16+ *
17+ * @param {type } trackPath
18+ * @param {type } callback
19+ * @returns {undefined }
20+ */
21+ analyzer . prototype . getData = function getDataFunction ( trackPath , callback ) {
22+
23+ // ffprobe file data
24+ var ffprobeSpawn = childProcess . spawn (
25+ 'ffprobe' ,
26+ [
27+ trackPath ,
28+ '-v' ,
29+ 'quiet' ,
30+ '-show_streams' ,
31+ '-show_format' ,
32+ '-print_format' ,
33+ 'json'
34+ ]
35+ ) ;
36+
37+ var stdoutOuputString = '' ;
38+ var stderrOuputString = '' ;
39+
40+ ffprobeSpawn . stdout . on ( 'data' , function ( data ) {
41+
42+ stdoutOuputString += data ;
43+
44+ } ) ;
45+
46+ var trackData = { } ;
47+
48+ ffprobeSpawn . stdout . on ( 'end' , function ( data ) {
49+
50+ console . log ( 'ffprobeSpawn stdout end' ) ;
51+
52+ if ( stdoutOuputString !== '' ) {
53+
54+ console . log ( 'stdoutOuput' ) ;
55+ //console.log(stdoutOuputString);
56+
57+ var stdoutOuput = JSON . parse ( stdoutOuputString ) ;
58+
59+ trackData . duration = stdoutOuput [ 'format' ] [ 'duration' ] ;
60+ trackData . size = stdoutOuput [ 'format' ] [ 'size' ] ;
61+ trackData . bitRate = stdoutOuput [ 'format' ] [ 'bit_rate' ] ;
62+ trackData . sampleRate = stdoutOuput [ 'streams' ] [ 0 ] [ 'sample_rate' ] ;
63+ trackData . channels = stdoutOuput [ 'streams' ] [ 0 ] [ 'channels' ] ;
64+
65+ }
66+
67+ } ) ;
68+
69+ ffprobeSpawn . stderr . setEncoding ( 'utf8' ) ;
70+
71+ ffprobeSpawn . stderr . on ( 'data' , function ( data ) {
72+
73+ stderrOuputString += data ;
74+
75+ } ) ;
76+
77+ ffprobeSpawn . stderr . on ( 'end' , function ( ) {
78+
79+ console . log ( 'ffprobeSpawn stderr end' ) ;
80+
81+ } ) ;
82+
83+ ffprobeSpawn . on ( 'exit' , function ( code ) {
84+
85+ console . log ( 'ffprobeSpawn exit, code: ' + code ) ;
86+
87+ if ( code > 0 ) {
88+
89+ callback ( stderrOuputString ) ;
90+
91+ } else {
92+
93+ if ( Object . keys ( trackData ) . length > 0 ) {
94+
95+ callback ( false , trackData ) ;
96+
97+ } else {
98+
99+ callback ( 'ffprobe did not output any data' ) ;
100+
101+ }
102+
103+ }
104+
105+ } ) ;
106+
107+ ffprobeSpawn . on ( 'close' , function ( ) {
108+
109+ console . log ( 'ffprobeSpawn close' ) ;
110+
111+ } ) ;
112+
113+ } ;
114+
115+ /**
116+ *
117+ * get pcm data of a track
118+ *
119+ * @param {type } trackPath
120+ * @param {type } callback
121+ * @returns {undefined }
122+ */
123+ analyzer . prototype . getPCMValues = function getValuesFunction ( trackPath , callback ) {
124+
125+ this . getData ( trackPath , function ( error , trackData ) {
126+
127+ if ( ! error ) {
128+
129+ console . log ( 'ffprobe track data: ' ) ;
130+ console . log ( trackData ) ;
131+
132+ // get audio pcm
133+ var ffmpegSpawn = childProcess . spawn (
134+ 'ffmpeg' ,
135+ [
136+ '-i' ,
137+ trackPath ,
138+ '-f' ,
139+ 's16le' ,
140+ '-ac' ,
141+ trackData . channels ,
142+ '-acodec' ,
143+ 'pcm_s16le' ,
144+ '-ar' ,
145+ trackData . sampleRate ,
146+ '-y' ,
147+ 'pipe:1'
148+ ]
149+ ) ;
150+
151+ var stdoutOuputString = '' ;
152+ var stderrOuputString = '' ;
153+
154+ // TODO: uncomment for ffprobe
155+ //ffmpegSpawn.stdout.setEncoding('utf8');
156+
157+ var oddByte = null ;
158+ var channel = 0 ;
159+
160+ //var outputCounter = 0;
161+
162+ var maxValue = 0 ;
163+
164+ //var output = [];
165+
166+ //var counter = 0;
167+
168+ ffmpegSpawn . stdout . on ( 'data' , function ( data ) {
169+
170+ // http://nodejs.org/api/buffer.html#buffer_buf_readint16le_offset_noassert
171+ // https://github.com/jhurliman/node-pcm/blob/master/lib/pcm.js
172+
173+ var value ;
174+ var i ;
175+ var dataLen = data . length ;
176+ var percentageOfMax = 0 ;
177+
178+ //counter++;
179+
180+ for ( i = 0 ; i < dataLen ; i += 2 ) {
181+
182+ value = data . readInt16LE ( i , true ) ;
183+
184+ //channel = ++channel % 2;
185+
186+ //console.log('B: ' + value + ' / ' + channel);
187+
188+ //outputCounter++;
189+
190+ //if (value > maxValue) maxValue = value;
191+
192+ // maxValue is 32767
193+
194+ // (value / maxValue)*100 = percentage of max
195+ percentageOfMax = ( value / 32767 ) * 100 ;
196+
197+ //return false;
198+
199+ //outputCounter++;
200+
201+ }
202+
203+ console . log ( i ) ;
204+
205+ //console.log('outputCounter: ' + outputCounter);
206+
207+ //console.log(maxValue); // 32767
208+
209+ // get absolute value
210+ //var absolutePercentageOfMaxMath = Math.abs(percentageOfMax);
211+
212+ //output.push(absolutePercentageOfMaxMath);
213+
214+ //console.log(absolutePercentageOfMaxMath);
215+
216+ /*var bar = '';
217+
218+ for (i=0; i < absolutePercentageOfMaxMath/10; i++) {
219+
220+ bar += '*';
221+
222+ }*/
223+
224+ //console.log(bar);
225+
226+ } ) ;
227+
228+ ffmpegSpawn . stdout . on ( 'end' , function ( data ) {
229+
230+ console . log ( 'ffmpegSpawn stdout end' ) ;
231+ //console.log(counter);
232+ //console.log(outputCounter);
233+
234+ if ( output . length > 0 ) {
235+
236+ callback ( false , output ) ;
237+
238+ } else {
239+
240+ callback ( 'no output recieved' ) ;
241+
242+ }
243+
244+ } ) ;
245+
246+ ffmpegSpawn . stderr . setEncoding ( 'utf8' ) ;
247+
248+ ffmpegSpawn . stderr . on ( 'data' , function ( data ) {
249+
250+ //console.log(data.toString());
251+
252+ } ) ;
253+
254+ ffmpegSpawn . stderr . on ( 'end' , function ( ) {
255+
256+ console . log ( 'ffmpegSpawn stderr end' ) ;
257+
258+ } ) ;
259+
260+ ffmpegSpawn . on ( 'exit' , function ( code ) {
261+
262+ console . log ( 'ffmpegSpawn exit, code: ' + code ) ;
263+
264+ } ) ;
265+
266+ ffmpegSpawn . on ( 'close' , function ( ) {
267+
268+ console . log ( 'ffmpegSpawn close' ) ;
269+
270+ } ) ;
271+
272+ } else {
273+
274+ callback ( error ) ;
275+
276+ }
277+
278+ } ) ;
279+
280+ } ;
281+
282+ module . exports . analyzer = analyzer ;
0 commit comments