Skip to content

Commit

Permalink
Added .duration and .frameCount, populated when for seekable video
Browse files Browse the repository at this point in the history
  • Loading branch information
phoboslab committed Jun 2, 2015
1 parent b2d57a1 commit 5ac302b
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 36 deletions.
18 changes: 8 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,18 @@ player.seekToTime(20); // Seek to intra frame before 20sec
player.seekToFrame(1200, true); // Seek to frame 1200 exactly


// Passing 'seekable: true' also populates the total frame count and duration
// of the video

console.log('Duration: '+player.duration+' seconds ('+frames+' player.frameCount)')



// An 'onload' callback can be specified in the 'options' argument
var mpegLoaded = function( player ) {
console.log('Loaded', player);

// calculateFrameCount() and calculateDuration() can only be called
// after the mpeg has been fully loaded. So this callback is the ideal
// place to fetch this info
var frames = player.calculateFrameCount(),
duration = player.calculateDuration();

console.log('Duration: '+duration+' seconds ('+frames+' frames)');
};

var player = new jsmpeg('file.mpeg', {onload:mpegLoaded});
var player = new jsmpeg('file.mpeg', {onload: mpegLoaded});

// If you don't use 'autoplay' and don't explicitly call .play(), you can get individual
// video frames (a canvas element) like so:
Expand Down
36 changes: 10 additions & 26 deletions jsmpg.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ jsmpeg.prototype.stopRecording = function() {
// Loading via Ajax

jsmpeg.prototype.intraFrames = [];
jsmpeg.prototype.frameCount = 0;
jsmpeg.prototype.duration = 0;

jsmpeg.prototype.load = function( url ) {
this.url = url;
Expand Down Expand Up @@ -320,6 +322,9 @@ jsmpeg.prototype.loadCallback = function(file) {
this.firstSequenceHeader = this.buffer.index;
this.decodeSequenceHeader();

// Calculate the duration. This only works if the video is seekable and we have a frame count.
this.duration = this.frameCount / this.pictureRate;

// Load the first frame
this.nextFrame();

Expand All @@ -334,7 +339,9 @@ jsmpeg.prototype.loadCallback = function(file) {

jsmpeg.prototype.collectIntraFrames = function() {
// Loop through the whole buffer and collect all intraFrames to build our seek index.
for( var frame = 0; this.findStartCode(START_PICTURE) !== BitReader.NOT_FOUND; frame++ ) {
// We also keep track of total frame count here
var frame;
for( frame = 0; this.findStartCode(START_PICTURE) !== BitReader.NOT_FOUND; frame++ ) {

// Check if the found picture is an intra frame and remember the position
this.buffer.advance(10); // skip temporalReference
Expand All @@ -343,6 +350,8 @@ jsmpeg.prototype.collectIntraFrames = function() {
this.intraFrames.push({frame: frame, index: this.buffer.index - 13});
}
}

this.frameCount = frame;
};

jsmpeg.prototype.seekToFrame = function(seekFrame, seekExact) {
Expand Down Expand Up @@ -430,31 +439,6 @@ jsmpeg.prototype.fillArray = function(a, value) {
}
};

jsmpeg.prototype.cachedFrameCount = 0;
jsmpeg.prototype.calculateFrameCount = function() {
if( !this.buffer || this.cachedFrameCount ) {
return this.cachedFrameCount;
}

// Remember the buffer position, so we can rewind to the beginning and
// reset to the current position afterwards
var currentPlaybackIndex = this.buffer.index,
frames = 0;

this.buffer.index = 0;
while( this.findStartCode(START_PICTURE) !== BitReader.NOT_FOUND ) {
frames++;
}
this.buffer.index = currentPlaybackIndex;

this.cachedFrameCount = frames;
return frames;
};

jsmpeg.prototype.calculateDuration = function() {
return this.calculateFrameCount() * (1/this.pictureRate);
};



// ----------------------------------------------------------------------------
Expand Down

0 comments on commit 5ac302b

Please sign in to comment.