Browse Source

duration.js -> probe.js

Noah 7 years ago
parent
commit
01145fc1e2
9 changed files with 89 additions and 91 deletions
  1. 0 35
      audiogram/duration.js
  2. 9 8
      audiogram/index.js
  3. 43 0
      audiogram/probe.js
  4. 3 3
      audiogram/trim.js
  5. 2 2
      client/index.js
  6. 1 0
      client/waveform.js
  7. 1 1
      package.json
  8. 1 1
      server/status.js
  9. 29 41
      test/duration-test.js

+ 0 - 35
audiogram/duration.js View File

@@ -1,35 +0,0 @@
1
-var probe = require("node-ffprobe");
2
-
3
-module.exports = function(filename, cb){
4
-
5
-  probe(filename, function(err, probeData) {
6
-
7
-    if (err) {
8
-      return cb(err);
9
-    }
10
-
11
-    var duration = getDuration(probeData);
12
-
13
-    if (!duration || duration === "N/A" || !(duration > 0)) {
14
-      return cb("Couldn't probe audio duration.");
15
-    }
16
-
17
-    return cb(null, duration);
18
-
19
-  });
20
-
21
-};
22
-
23
-function getDuration(probeData) {
24
-
25
-  if (probeData.format && probeData.format.duration) {
26
-    return probeData.format.duration;
27
-  }
28
-
29
-  if (Array.isArray(probeData.streams) && probeData.streams.length && probeData.streams[0].duration) {
30
-    return probeData.streams[0].duration;
31
-  }
32
-
33
-  return null;
34
-
35
-}

+ 9 - 8
audiogram/index.js View File

@@ -5,7 +5,7 @@ var path = require("path"),
5 5
     serverSettings = require("../settings/"),
6 6
     transports = require("../lib/transports/"),
7 7
     logger = require("../lib/logger/"),
8
-    getDuration = require("./duration.js"),
8
+    probe = require("./probe.js"),
9 9
     getWaveform = require("./waveform.js"),
10 10
     initializeCanvas = require("./initialize-canvas.js"),
11 11
     drawFrames = require("./draw-frames.js"),
@@ -29,24 +29,25 @@ function Audiogram(settings) {
29 29
 
30 30
 }
31 31
 
32
-// Probe an audio file for its duration, compute the number of frames required
33
-Audiogram.prototype.getDuration = function(cb) {
32
+// Probe an audio file for its duration and # of channels, compute the number of frames required
33
+Audiogram.prototype.probe = function(cb) {
34 34
 
35 35
   var self = this;
36 36
 
37
-  this.status("duration");
37
+  this.status("probing");
38 38
 
39
-  getDuration(this.audioPath, function(err, duration){
39
+  probe(this.audioPath, function(err, data){
40 40
 
41 41
     if (err) {
42 42
       return cb(err);
43 43
     }
44 44
 
45
-    if (self.settings.maxDuration && self.settings.maxDuration < duration) {
45
+    if (self.settings.maxDuration && self.settings.maxDuration < data.duration) {
46 46
       cb("Exceeds max duration of " + self.settings.maxDuration + "s");
47 47
     }
48 48
 
49
-    self.set("numFrames", self.numFrames = Math.floor(duration * self.settings.framesPerSecond));
49
+    self.set("numFrames", self.numFrames = Math.floor(data.duration * self.settings.framesPerSecond));
50
+    self.channels = data.channels;
50 51
 
51 52
     cb(null);
52 53
 
@@ -160,7 +161,7 @@ Audiogram.prototype.render = function(cb) {
160 161
   }
161 162
 
162 163
   // Get the audio's duration for computing number of frames
163
-  q.defer(this.getDuration.bind(this));
164
+  q.defer(this.probe.bind(this));
164 165
 
165 166
   // Get the audio waveform data
166 167
   q.defer(this.getWaveform.bind(this));

+ 43 - 0
audiogram/probe.js View File

@@ -0,0 +1,43 @@
1
+var probe = require("node-ffprobe");
2
+
3
+module.exports = function(filename, cb){
4
+
5
+  probe(filename, function(err, probeData) {
6
+
7
+    if (err) {
8
+      return cb(err);
9
+    }
10
+
11
+    var duration = getProperty(probeData, "duration"),
12
+        channels = getProperty(probeData, "channels");
13
+
14
+    if (!duration || duration === "N/A" || !(duration > 0)) {
15
+      return cb("Couldn't probe audio duration.");
16
+    }
17
+
18
+    if (typeof channels !== "number" || channels < 1 || channels > 2) {
19
+      return cb("Couldn't detect mono/stereo channels");
20
+    }
21
+
22
+    return cb(null, {
23
+      duration: duration,
24
+      channels: channels
25
+    });
26
+
27
+  });
28
+
29
+};
30
+
31
+function getProperty(probeData, property) {
32
+
33
+  if (probeData.format && probeData.format[property]) {
34
+    return probeData.format[property];
35
+  }
36
+
37
+  if (Array.isArray(probeData.streams) && probeData.streams.length && probeData.streams[0][property]) {
38
+    return probeData.streams[0][property];
39
+  }
40
+
41
+  return null;
42
+
43
+}

+ 3 - 3
audiogram/trim.js View File

@@ -1,16 +1,16 @@
1 1
 var exec = require("child_process").exec,
2
-    getDuration = require("./duration.js");
2
+    probe = require("./probe.js");
3 3
 
4 4
 function trimAudio(options, cb) {
5 5
 
6 6
   if (!options.endTime) {
7 7
 
8
-    return getDuration(options.origin, function(err, duration){
8
+    return probe(options.origin, function(err, data){
9 9
       if (err) {
10 10
         return cb(err);
11 11
       }
12 12
 
13
-      options.endTime = duration;
13
+      options.endTime = data.duration;
14 14
       trimAudio(options, cb);
15 15
 
16 16
     });

+ 2 - 2
client/index.js View File

@@ -266,8 +266,8 @@ function statusMessage(result) {
266 266
       return "Downloading audio for processing";
267 267
     case "trim":
268 268
       return "Trimming audio";
269
-    case "duration":
270
-      return "Checking duration";
269
+    case "probing":
270
+      return "Probing audio file";
271 271
     case "waveform":
272 272
       return "Analyzing waveform";
273 273
     case "renderer":

+ 1 - 0
client/waveform.js View File

@@ -38,6 +38,7 @@ module.exports = function(file, cb) {
38 38
   var fileReader = new FileReader();
39 39
 
40 40
   var close = function(err, data) {
41
+    console.warn(err);
41 42
     ctx.close();
42 43
     cb(err, data);
43 44
   };

+ 1 - 1
package.json View File

@@ -25,6 +25,7 @@
25 25
   "dependencies": {
26 26
     "aws-sdk": "^2.2.39",
27 27
     "browserify": "^13.0.0",
28
+    "canvas": "git+https://github.com/chearon/node-canvas.git#b62dd3a9fa",
28 29
     "compression": "^1.6.1",
29 30
     "d3": "^4.1.1",
30 31
     "dotenv": "^2.0.0",
@@ -39,7 +40,6 @@
39 40
     "rimraf": "^2.5.0",
40 41
     "smartquotes": "^1.0.0",
41 42
     "underscore": "^1.8.3",
42
-    "canvas": "git+https://github.com/chearon/node-canvas.git#b62dd3a9fa",
43 43
     "waveform": "git+https://github.com/veltman/node-waveform.git#8b1a22f109",
44 44
     "webaudio-peaks": "0.0.5",
45 45
     "winston": "^2.2.0"

+ 1 - 1
server/status.js View File

@@ -30,7 +30,7 @@ module.exports = function(req, res) {
30 30
         hash = { status: "unknown" };
31 31
       }
32 32
 
33
-      ["duration","numFrames","framesComplete"].forEach(function(key) {
33
+      ["numFrames", "framesComplete"].forEach(function(key) {
34 34
         if (key in hash) {
35 35
           hash[key] = +hash[key];
36 36
         }

+ 29 - 41
test/duration-test.js View File

@@ -5,38 +5,40 @@ var tape = require("tape"),
5 5
 
6 6
 require("mkdirp").sync(path.join(__dirname, "tmp"));
7 7
 
8
-var getDuration = require("../audiogram/duration.js"),
8
+var probe = require("../audiogram/probe.js"),
9 9
     trimAudio = require("../audiogram/trim.js");
10 10
 
11
-tape("MP3 duration", function(test) {
11
+tape("MP3 probe", function(test) {
12 12
 
13
-  getDuration(path.join(__dirname, "data/glazed-donut.mp3"), function(err, duration){
13
+  probe(path.join(__dirname, "data/glazed-donut.mp3"), function(err, data){
14 14
 
15 15
     test.error(err);
16
-    test.equal(typeof duration, "number");
17
-    test.assert(Math.abs(duration - 26.67) < 0.1);
16
+    test.equal(typeof data.duration, "number");
17
+    test.equal(data.channels, 2);
18
+    test.assert(Math.abs(data.duration - 26.67) < 0.1);
18 19
     test.end();
19 20
 
20 21
   });
21 22
 
22 23
 });
23 24
 
24
-tape("WAV duration", function(test) {
25
+tape("WAV probe", function(test) {
25 26
 
26
-  getDuration(path.join(__dirname, "data/glazed-donut.wav"), function(err, duration){
27
+  probe(path.join(__dirname, "data/glazed-donut.wav"), function(err, data){
27 28
 
28 29
     test.error(err);
29
-    test.equal(typeof duration, "number");
30
-    test.assert(Math.abs(duration - 1.83) < 0.1);
30
+    test.equal(typeof data.duration, "number");
31
+    test.equal(data.channels, 2);
32
+    test.assert(Math.abs(data.duration - 1.83) < 0.1);
31 33
     test.end();
32 34
 
33 35
   });
34 36
 
35 37
 });
36 38
 
37
-tape("Duration error", function(test) {
39
+tape("Probe error", function(test) {
38 40
 
39
-  getDuration(path.join(__dirname, "..", "README.md"), function(err){
41
+  probe(path.join(__dirname, "..", "README.md"), function(err){
40 42
 
41 43
     test.ok(err);
42 44
     test.end();
@@ -55,12 +57,12 @@ tape("Trim start", function(test) {
55 57
 
56 58
   queue(1)
57 59
     .defer(trimAudio, options)
58
-    .defer(getDuration, options.destination)
59
-    .await(function(err, _, duration){
60
+    .defer(probe, options.destination)
61
+    .await(function(err, _, data){
60 62
 
61 63
       test.error(err);
62
-      test.equal(typeof duration, "number");
63
-      test.assert(Math.abs(duration - 20) < 0.1);
64
+      test.equal(typeof data.duration, "number");
65
+      test.assert(Math.abs(data.duration - 20) < 0.1);
64 66
       test.end();
65 67
 
66 68
     });
@@ -77,12 +79,12 @@ tape("Trim end", function(test) {
77 79
 
78 80
   queue(1)
79 81
     .defer(trimAudio, options)
80
-    .defer(getDuration, options.destination)
81
-    .await(function(err, _, duration){
82
+    .defer(probe, options.destination)
83
+    .await(function(err, _, data){
82 84
 
83 85
       test.error(err);
84
-      test.equal(typeof duration, "number");
85
-      test.assert(Math.abs(duration - 20) < 0.1);
86
+      test.equal(typeof data.duration, "number");
87
+      test.assert(Math.abs(data.duration - 20) < 0.1);
86 88
       test.end();
87 89
 
88 90
     });
@@ -100,12 +102,12 @@ tape("Trim start & end", function(test) {
100 102
 
101 103
   queue(1)
102 104
     .defer(trimAudio, options)
103
-    .defer(getDuration, options.destination)
104
-    .await(function(err, _, duration){
105
+    .defer(probe, options.destination)
106
+    .await(function(err, _, data){
105 107
 
106 108
       test.error(err);
107
-      test.equal(typeof duration, "number");
108
-      test.assert(Math.abs(duration - 5) < 0.1);
109
+      test.equal(typeof data.duration, "number");
110
+      test.assert(Math.abs(data.duration - 5) < 0.1);
109 111
       test.end();
110 112
 
111 113
     });
@@ -122,25 +124,11 @@ tape("Trim invalid", function(test) {
122 124
     endTime: 4
123 125
   };
124 126
 
125
-  queue(1)
126
-    .defer(trimAudio, options)
127
-    .defer(getDuration, options.destination)
128
-    .await(function(err, _, duration){
129
-
130
-      test.ok(err);
131
-      test.end();
132
-
133
-    });
134
-
135
-});
136
-
137
-// Cleanup
138
-tape.onFinish(function(){
139
-  require("rimraf")(path.join(__dirname, "tmp"), function(err){
140
-    if (err) {
141
-      throw err;
142
-    }
127
+  trimAudio(options, function(err){
128
+    test.ok(err);
129
+    test.end();
143 130
   });
131
+
144 132
 });
145 133
 
146 134
 // Cleanup