-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from LCMApps/network-stats-function
Network stats function
- Loading branch information
Showing
7 changed files
with
346 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
const {FramesMonitor, processFrames} = require('../index'); | ||
// or | ||
// const {processFrames} = require('video-quality-tools'); | ||
// if you use it outside this repo | ||
|
||
const INTERVAL_TO_ANALYZE_FRAMES = 5000; // in milliseconds | ||
const STREAM_URI = 'rtmp://host:port/path'; | ||
|
||
const framesMonitorOptions = { | ||
ffprobePath: '/usr/local/bin/ffprobe', | ||
timeoutInSec: 5, | ||
bufferMaxLengthInBytes: 100000, | ||
errorLevel: 'error', | ||
exitProcessGuardTimeoutInMs: 1000 | ||
}; | ||
|
||
const framesMonitor = new FramesMonitor(framesMonitorOptions, STREAM_URI); | ||
|
||
let frames = []; | ||
|
||
function firstVideoFrameListener(frame) { | ||
if (frame.media_type === 'video') { | ||
framesMonitor.removeListener('frame', firstVideoFrameListener); | ||
framesMonitor.on('frame', frameListener); | ||
startAnalysis(); | ||
} | ||
} | ||
|
||
function frameListener(frame) { | ||
frames.push(frame); | ||
} | ||
|
||
function startAnalysis() { | ||
setInterval(() => { | ||
try { | ||
const info = processFrames.networkStats(frames, INTERVAL_TO_ANALYZE_FRAMES); | ||
|
||
console.log(info); | ||
|
||
frames = []; | ||
} catch (err) { | ||
// only if arguments are invalid | ||
console.log(err); | ||
process.exit(1); | ||
} | ||
}, INTERVAL_TO_ANALYZE_FRAMES); | ||
} | ||
|
||
// We listens first video frame to start processing. We do such thing to avoid incorrect stats for the first | ||
// run of networkStats function after the first interval. | ||
framesMonitor.on('frame', firstVideoFrameListener); | ||
|
||
framesMonitor.on('exit', reason => { | ||
console.log('EXIT', reason); | ||
process.exit(); | ||
}); | ||
|
||
framesMonitor.listen(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
'use strict'; | ||
|
||
const invalidFramesTypes = [ | ||
undefined, | ||
null, | ||
false, | ||
1, | ||
'1', | ||
{}, | ||
Symbol(), | ||
() => {}, | ||
Buffer.alloc(0) | ||
]; | ||
|
||
const invalidDurationInSecTypes = [ | ||
undefined, | ||
null, | ||
false, | ||
[], | ||
[1, 2], | ||
'1', | ||
1.2, | ||
-1, | ||
{}, | ||
Symbol(), | ||
() => {}, | ||
Buffer.alloc(0) | ||
]; | ||
|
||
const testData = [ | ||
{ | ||
description: 'empty frames array', | ||
frames : [], | ||
durationInMsec: 1000, | ||
expected : { | ||
videoFrameRate: 0, | ||
audioFrameRate: 0, | ||
videoBitrate: 0, | ||
audioBitrate: 0, | ||
}, | ||
}, | ||
{ | ||
description : 'audio only frames with 1000 msec duration', | ||
frames : [ | ||
{pkt_size: 2, pkt_pts_time: 10, media_type: 'audio', key_frame: 1}, | ||
{pkt_size: 3, pkt_pts_time: 11, media_type: 'audio', key_frame: 1}, | ||
], | ||
durationInMsec: 1000, | ||
expected : { | ||
videoFrameRate: 0, | ||
audioFrameRate: 2, | ||
videoBitrate: 0, | ||
audioBitrate: 0.0390625, | ||
}, | ||
}, | ||
{ | ||
description : 'video only frames with 1000 msec duration', | ||
frames : [ | ||
{width: 854, height: 480, pkt_size: 2, pkt_pts_time: 1, media_type: 'video', key_frame: 1, pict_type: 'P'}, | ||
{width: 854, height: 480, pkt_size: 3, pkt_pts_time: 10, media_type: 'video', key_frame: 0, pict_type: 'P'}, | ||
], | ||
durationInMsec: 1000, | ||
expected : { | ||
videoFrameRate: 2, | ||
audioFrameRate: 0, | ||
videoBitrate: 0.0390625, | ||
audioBitrate: 0, | ||
}, | ||
}, | ||
{ | ||
description : 'frames with 200 msec duration', | ||
frames : [ | ||
{width: 854, height: 480, pkt_size: 2, pkt_pts_time: 1, media_type: 'video', key_frame: 1, pict_type: 'P'}, | ||
{pkt_size: 2, pkt_pts_time: 10, media_type: 'audio', key_frame: 1}, | ||
{pkt_size: 3, pkt_pts_time: 11, media_type: 'audio', key_frame: 1}, | ||
{width: 854, height: 480, pkt_size: 3, pkt_pts_time: 10, media_type: 'video', key_frame: 0, pict_type: 'P'}, | ||
{pkt_size: 4, pkt_pts_time: 12, media_type: 'audio', key_frame: 1}, | ||
], | ||
durationInMsec: 200, | ||
expected : { | ||
videoFrameRate: 10, | ||
audioFrameRate: 15, | ||
videoBitrate: 0.1953125, | ||
audioBitrate: 0.3515625, | ||
}, | ||
}, | ||
{ | ||
description : 'audio only frames with 2000 msec duration', | ||
frames : [ | ||
{width: 854, height: 480, pkt_size: 5, pkt_pts_time: 1, media_type: 'video', key_frame: 1, pict_type: 'P'}, | ||
{pkt_size: 2, pkt_pts_time: 10, media_type: 'audio', key_frame: 1}, | ||
{pkt_size: 3, pkt_pts_time: 11, media_type: 'audio', key_frame: 1}, | ||
{width: 854, height: 480, pkt_size: 6, pkt_pts_time: 10, media_type: 'video', key_frame: 0, pict_type: 'P'}, | ||
{pkt_size: 4, pkt_pts_time: 12, media_type: 'audio', key_frame: 1}, | ||
{width: 854, height: 480, pkt_size: 7, pkt_pts_time: 10, media_type: 'video', key_frame: 0, pict_type: 'I'}, | ||
], | ||
durationInMsec: 2000, | ||
expected : { | ||
videoFrameRate: 1.5, | ||
audioFrameRate: 1.5, | ||
videoBitrate: 0.0703125, | ||
audioBitrate: 0.03515625, | ||
}, | ||
}, | ||
]; | ||
|
||
module.exports = { | ||
invalidFramesTypes, | ||
invalidDurationInSecTypes, | ||
testData | ||
}; | ||
|
Oops, something went wrong.