add test for file analysis. hotlist output bugfix

This commit is contained in:
Alexandre Storelli 2019-03-11 22:30:01 +01:00
parent 2889e7de11
commit 783c1e8a6a
7 changed files with 1585 additions and 7 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@ log/
model/
node_modules/
records/
test/file.mp3.json
.vscode/
podcasts/
webradio-metadata.js

1382
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
"description": "Distinguish ads, talk and music in radios",
"main": "post-processing.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "mocha --delay"
},
"keywords": [
"adblock",
@ -31,6 +31,7 @@
"aws-sdk": "^2.408.0",
"electron-builder": "^20.38.5",
"electron-prebuilt": "^1.4.13",
"electron-rebuild": "^1.8.4"
"electron-rebuild": "^1.8.4",
"mocha": "^6.0.2"
}
}

View File

@ -25,6 +25,10 @@ const consts = {
}
}
const toFixed = function(num, digits) {
return Math.round(num * Math.pow(10, digits)) / Math.pow(10, digits);
}
class Hotlist extends Writable {
constructor(options) {
super({ objectMode: true });
@ -262,11 +266,11 @@ class Hotlist extends Writable {
fingersCountMeasurements: tcodes.length, // amount of fingerprints generated by measurements
// confidence factors
ratioFingersReference: ratioFingersReference.toFixed(5),
ratioFingersMeasurements: ratioFingersMeasurements.toFixed(5),
matchingFocus: matchingFocus.toFixed(5),
confidence1: confidence1.toFixed(5),
confidence2: confidence2.toFixed(5),
ratioFingersReference: toFixed(ratioFingersReference, 5),
ratioFingersMeasurements: toFixed(ratioFingersMeasurements, 5),
matchingFocus: toFixed(matchingFocus, 5),
confidence1: toFixed(confidence1, 5),
confidence2: toFixed(confidence2, 5),
softmaxraw: softmax,
}

View File

@ -83,6 +83,7 @@ class MlPredictor extends Writable {
_final() {
if (this.child) {
this.child.kill();
log.info(this.canonical + " killed child process.");
}
}
}

189
test/file.js Normal file
View File

@ -0,0 +1,189 @@
const { log } = require("abr-log")("test-file");
const { Analyser } = require("../post-processing.js");
const fs = require("fs-extra");
const assert = require("assert");
const cluster = require("cluster");
const FILE = __dirname + '/file.mp3';
const TEST_ML = true;
const TEST_HOTLIST = true;
const PRED_INTERVAL = 1; // in seconds
if (cluster.isMaster) {
const TIMEOUT = 30000; // this must be at least the length of the audio tested
let cp = null;
let gotData = false;
let finished = false;
let hasErrors = false;
let exited = false;
let exitCode = null;
let timedOut = false;
let fileOutput = {};
let fileOutputIsSane = false;
const timer = setTimeout(function() {
log.error('analysis timed out or was too slow. kill it.');
timedOut = true;
console.log(getEventListeners(node));
cp.kill();
run();
}, TIMEOUT);
fs.unlink(FILE + '.json', function(err) {
// we ignore err here.
cp = cluster.fork();
cp.on('message', function(msg) {
if (msg.type === 'data') {
if (msg.data) {
gotData = true;
}
} else if (msg.type === 'end') {
finished = true;
}
});
cp.on('error', function(err) {
log.error('child process had an error: ' + err);
hasErrors = true;
});
cp.on('exit', function(code) {
exited = true;
exitCode = code;
clearTimeout(timer);
fs.readFile(FILE + '.json', function(err, data) {
try {
fileOutput = JSON.parse(data);
fileOutputIsSane = true;
} catch (e) {
fileOutputIsSane = false;
}
run();
});
});
});
// for debug purposes. test the previous results directly, without redoing the computations
// if you want to do so, comment out the code above
/*fs.readFile(FILE + '.json', function(err, data) {
fileOutputIsSane = true;
fileOutput = JSON.parse(data);
run();
});*/
describe('File analysis', function() {
it("should have emitted data", function() {
assert(gotData);
});
it("should have reached the end of the file", function() {
assert(finished);
});
it("should not have thrown errors", function() {
assert(!hasErrors);
});
it("should have exited properly", function() {
assert(exited);
assert.equal(exitCode, 0);
assert(!timedOut);
});
it("should write results in JSON format", function() {
assert(fileOutputIsSane);
assert(fileOutput.country);
assert(fileOutput.name);
const blocks = [fileOutput.blocksRaw, fileOutput.blocksCoarse, fileOutput.blocksCleaned];
for (let ib = 0; ib<blocks.length; ib++) {
const block = blocks[ib];
assert(block.length);
for (let i=0; i<block.length; i++) {
assert(!isNaN(block[i].tStart));
assert(!isNaN(block[i].tEnd));
assert(['0-ads', '1-speech', '2-music', '3-jingles', 'unsure'].includes(block[i].class));
}
}
assert(fileOutput.predictions);
for (let i=0; i<fileOutput.predictions.length; i++) {
const p = fileOutput.predictions[i];
assert(p);
if (TEST_ML) {
assert(p.gain > 60 && p.gain < 85);
assert(p.ml);
assert(['0-ads', '1-speech', '2-music'].includes(p.ml.class));
assert(p.ml.softmaxraw);
assert.equal(p.ml.softmaxraw.length, 4);
assert(p.ml.softmax);
assert.equal(p.ml.softmax.length, 4);
assert(!isNaN(p.ml.slotsFuture));
assert(!isNaN(p.ml.slotsPast));
} else {
assert.equal(p.ml, null);
}
if (TEST_HOTLIST) {
assert(p.hotlist);
assert(['0-ads', '1-speech', '2-music', '3-jingles', 'unsure'].includes(p.hotlist.class));
assert(p.hotlist.softmaxraw);
assert.equal(p.hotlist.softmaxraw.length, 4);
assert(p.hotlist.softmax);
assert.equal(p.hotlist.softmax.length, 4);
assert(!isNaN(p.hotlist.matchesSync));
assert(!isNaN(p.hotlist.matchesTotal));
assert(!isNaN(p.hotlist.confidence1));
assert(0 <= p.hotlist.confidence1);
assert(p.hotlist.confidence1 <= 1);
assert(!isNaN(p.hotlist.confidence2));
assert(0 <= p.hotlist.confidence2);
assert(p.hotlist.confidence2 <= 1);
} else {
assert.equal(p.hotlist, null);
}
assert(['0-ads', '1-speech', '2-music', '3-jingles', 'unsure'].includes(p.class));
assert(!isNaN(p.tStart));
assert(!isNaN(p.tEnd));
assert(p.tEnd > p.tStart);
assert(p.tEnd <= p.tStart + PRED_INTERVAL * 1000);
}
});
});
} else {
const t1 = new Date();
const abr = new Analyser({
country: "France",
name: "RTL",
config: {
file: FILE,
predInterval: PRED_INTERVAL,
enablePredictorHotlist: TEST_HOTLIST,
enablePredictorMl: TEST_ML,
saveMetadata: true,
verbose: false,
}
});
abr.on("data", function(obj) {
//log.info(JSON.stringify(obj, null, "\t"));
process.send({ type: 'data', data: obj });
});
abr.on("end", function() {
const t2 = new Date();
log.info("finished analysing file " + FILE + " in " + (+t2-t1)/1000 + " seconds");
process.send({ type: 'end' });
process.disconnect(); // otherwise the IPC prevents the subprocess from gracefully exiting
});
}

BIN
test/file.mp3 Normal file

Binary file not shown.