smpte-timecode
Advanced tools
+1
-1
| { | ||
| "name": "smpte-timecode", | ||
| "version": "1.1.0", | ||
| "version": "1.2.0", | ||
| "description": "JavaScript implementation of SMPTE timecode type", | ||
@@ -5,0 +5,0 @@ "main": "smpte-timecode.js", |
+17
-8
@@ -32,6 +32,6 @@ # smpte-timecode | ||
| - `timecode`: number, string or Date | ||
| Numbers are interpreted as frame count. | ||
| Strings are expected as `"HH:MM:SS:FF"` (non-drop-frame) or | ||
| `"HH:MM:SS;FF"` (drop-frame). | ||
| If Date() is passed, it is converted to the timecode a master | ||
| - Numbers are interpreted as frame count. | ||
| - Strings are expected as `"HH:MM:SS:FF"` (non-drop-frame) or | ||
| `"HH:MM:SS;FF"` (drop-frame). The constructor will throw if the string contains invalid timecode, for example frame count above framerate or 0 frames in a drop-frame second. | ||
| - If `Date()` is passed, it is converted to the timecode a master | ||
| clock would have with a given framerate. Month, date and | ||
@@ -41,3 +41,3 @@ year discarded. | ||
| - `frameRate`: number, optional | ||
| one of 24, 25, 29.97, 30, 50, 60 is expected. | ||
| one of 24, 25, 29.97, 30, 50, 59.94, or 60 is expected. | ||
| 29.97 is assumed if the parameter is omitted. | ||
@@ -48,4 +48,4 @@ | ||
| If omitted, and `timecode` is a string, the drop-frame mode is determined based on | ||
| the ":" or ";" characters separating the frames in the `timecode` parameter. | ||
| If `timecode` parameter is not a string, drop-frame assumed for 29.97 framerate, non-drop-frame for all other framerates. | ||
| the ":" or ";" characters separating the frames in the `timecode` parameter. | ||
| If `timecode` parameter is not a string, drop-frame assumed for 29.97 and 59.94 framerates, non-drop-frame for all others. | ||
@@ -85,2 +85,3 @@ Examples: | ||
| - `toString()`: string, returns the timecode in "HH:MM:SS:FF" or "HH:MM:SS;FF" format | ||
| - `toString('field')`: string, returns the timecode in VITC format, where timecodes above 30fps are represented as frame.field, i.e. HH:MM:SS:FF.f | ||
| - `toDate()`: date, returns a `Date` object using today's date and timecode as wall clock | ||
@@ -92,3 +93,3 @@ - `valueOf()`: number, returns `this.frameCount` | ||
| ## Running Tests | ||
| To run tests, make sure you install `expect.js`, `mocha` and `istanbul` NPMs **locally**. | ||
| To run tests, make sure you install `expect.js`, `mocha`, `codecov` and `istanbul` NPMs **locally**. | ||
@@ -104,2 +105,10 @@ npm install expect.js mocha istanbul codecov | ||
| ## Update History | ||
| - 1.2.0 | ||
| - Added support for 59.94 fps drop-frame expressed without fields - i.e. 00:00:00;59 is 1 frame short of a second; | ||
| - Added `.ToString('field')` output in HH:MM:SS;FF.f format; | ||
| - 1.1.0 | ||
| - Fixed the problem with Timecode.add(0) subtracting the frameCount for drop frame timecodes | ||
| ## Credits | ||
@@ -106,0 +115,0 @@ - [https://www.npmjs.com/package/timecode](https://www.npmjs.com/package/timecode) |
+30
-15
@@ -23,3 +23,3 @@ // This should work both in node and in the browsers, so that's what this wrapper is about | ||
| if (this.frameRate!=24 && this.frameRate!=25 && this.frameRate!=29.97 && this.frameRate!=30 && | ||
| this.frameRate!=50 && this.frameRate!=60 | ||
| this.frameRate!=50 && this.frameRate!=59.94 && this.frameRate!=60 | ||
| ) throw new Error('Unsupported framerate'); | ||
@@ -29,3 +29,3 @@ | ||
| if (typeof dropFrame === 'boolean') this.dropFrame = dropFrame; | ||
| else this.dropFrame = (this.frameRate==29.97); // by default, assume DF for 29.97, NDF otherwise | ||
| else this.dropFrame = (this.frameRate==29.97 || this.frameRate==59.94); // by default, assume DF for 29.97 and 59.94, NDF otherwise | ||
@@ -50,3 +50,3 @@ // Now either get the frame count, string or datetime | ||
| this.frames>=this.frameRate || | ||
| (this.dropFrame && this.frames<2 && this.seconds==0 && this.minutes%10 ) | ||
| (this.dropFrame && this.seconds==0 && this.minutes%10 && this.frames<2*(this.frameRate/29.97) ) | ||
| ) throw new Error("Invalid timecode") | ||
@@ -65,4 +65,6 @@ } | ||
| // Make sure dropFrame is only for 29.97 | ||
| if (this.dropFrame && this.frameRate!=29.97) throw new Error('Drop frame is only supported for 29.97fps'); | ||
| // Make sure dropFrame is only for 29.97 & 59.94 | ||
| if (this.dropFrame && this.frameRate!=29.97 && this.frameRate!=59.94) { | ||
| throw new Error('Drop frame is only supported for 29.97 and 59.94 fps'); | ||
| } | ||
@@ -86,8 +88,7 @@ // Now, if we have frameCount we need to calculate hours minutes seconds frames, vice versa | ||
| if (this.dropFrame) { | ||
| // var df = this.frameRate==29.97 ? 2 : 4; // 59.94 is 4 frames, we'll support it some day | ||
| var df = 2; | ||
| var d = Math.floor(this.frameCount / 17982); | ||
| var m = this.frameCount % 17982; | ||
| if (m<2) m=m+2; | ||
| fc = this.frameCount + 9*df*d + df*(Math.floor((m-2)/1798)); | ||
| var df = this.frameRate==29.97 ? 2 : 4; // 59.94 skips 4 frames | ||
| var d = Math.floor(this.frameCount / (17982*df/2)); | ||
| var m = this.frameCount % (17982*df/2); | ||
| if (m<df) m=m+df; | ||
| fc = this.frameCount + 9*df*d + df*(Math.floor((m-df)/(1798*df/2))); | ||
| } | ||
@@ -109,3 +110,4 @@ var fps = Math.round(this.frameRate); | ||
| var totalMinutes = this.hours*60 + this.minutes; | ||
| this.frameCount = this.frameCount - 2 * (totalMinutes - Math.floor(totalMinutes/10)); | ||
| var df = this.frameRate == 29.97 ? 2 : 4; | ||
| this.frameCount = this.frameCount - df * (totalMinutes - Math.floor(totalMinutes/10)); | ||
| } | ||
@@ -118,3 +120,15 @@ }; | ||
| */ | ||
| Timecode.prototype.toString = function TimeCodeToString() { | ||
| Timecode.prototype.toString = function TimeCodeToString(format) { | ||
| var frames = this.frames; | ||
| var field = ''; | ||
| if (typeof format == 'string') { | ||
| if (format == 'field') { | ||
| if (this.frameRate<=30) field = '.0'; | ||
| else { | ||
| frames = Math.floor(frames/2); | ||
| field = '.'.concat((this.frameCount%2).toString()); | ||
| }; | ||
| } | ||
| else throw new Error('Unsupported string format'); | ||
| }; | ||
| return "".concat( | ||
@@ -130,4 +144,5 @@ this.hours<10 ? '0' : '', | ||
| this.dropFrame ? ';' : ':', | ||
| this.frames<10 ? '0' : '', | ||
| this.frames.toString() | ||
| frames<10 ? '0' : '', | ||
| frames.toString(), | ||
| field | ||
| ); | ||
@@ -134,0 +149,0 @@ }; |
@@ -60,7 +60,9 @@ | ||
| expect(Timecode(1,29.97).dropFrame).to.be(true); | ||
| expect(Timecode(1,59.94).dropFrame).to.be(true); | ||
| expect(Timecode(1,25).dropFrame).to.be(false); | ||
| }); | ||
| it ('drop-frame only for 29.97', function() { | ||
| it ('drop-frame only for 29.97 and 59.94', function() { | ||
| expect(function(){Timecode(0,30,true)}).to.throwException(); | ||
| expect(function(){Timecode(0,59.94,true)}).to.not.throwException(); | ||
| }); | ||
@@ -70,8 +72,18 @@ | ||
| expect(Timecode('00:10:00;00').frameCount).to.be(17982); | ||
| expect(Timecode('00:10:00;00',59.94).frameCount).to.be(17982*2); | ||
| expect(Timecode('10:00:00;00').frameCount).to.be(1078920); | ||
| expect(Timecode('10:00:00;00',59.94).frameCount).to.be(1078920*2); | ||
| expect(function(){Timecode('00:02:00;00')}).to.throwError(); | ||
| expect(function(){Timecode('00:02:00;02')}).to.not.throwError(); | ||
| expect(function(){Timecode('00:02:00;00',59.94)}).to.throwError(); | ||
| expect(function(){Timecode('00:02:00;02',59.94)}).to.throwError(); | ||
| expect(function(){Timecode('00:02:00;04',59.94)}).to.not.throwError(); | ||
| expect(Timecode('00:01:59;29').frameCount).to.be(3597); | ||
| expect(Timecode('00:01:59;59',59.94).frameCount).to.be(3597*2+1); | ||
| expect(Timecode(17982,29.97,true).toString()).to.be('00:10:00;00'); | ||
| expect(Timecode(1078920,29.97,true).toString()).to.be('10:00:00;00'); | ||
| expect(Timecode(3597,29.97,true).toString()).to.be('00:01:59;29'); | ||
| expect(Timecode(17982*2,59.94,true).toString()).to.be('00:10:00;00'); | ||
| expect(Timecode(1078920*2,59.94,true).toString()).to.be('10:00:00;00'); | ||
| expect(Timecode(3597*2+1,59.94,true).toString()).to.be('00:01:59;59'); | ||
| }); | ||
@@ -93,2 +105,4 @@ it ('non-drop-frame counts', function() { | ||
| expect(Timecode('01:02:03;04').toString()).to.be('01:02:03;04'); | ||
| expect(Timecode('12:34:56;57',59.94).toString()).to.be('12:34:56;57'); | ||
| expect(Timecode('01:02:03;04',59.94).toString()).to.be('01:02:03;04'); | ||
| }); | ||
@@ -99,2 +113,11 @@ it ('implicit calls to toString()',function(){ | ||
| }); | ||
| it ('toString(\'field\')',function(){ | ||
| expect(Timecode('12:34:56;23').toString('field')).to.be('12:34:56;23.0'); | ||
| expect(Timecode('01:02:03;04').toString('field')).to.be('01:02:03;04.0'); | ||
| expect(Timecode('12:34:56;57',59.94).toString('field')).to.be('12:34:56;28.1'); | ||
| expect(Timecode('01:02:03;04',59.94).toString('field')).to.be('01:02:03;02.0'); | ||
| }); | ||
| it ('toString(\'unknown-format\')',function(){ | ||
| expect(function() {Timecode('12:34:56;23').toString('unknown-format')}).to.throwException(); | ||
| }); | ||
| }); | ||
@@ -101,0 +124,0 @@ |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
23848
13.79%326
13.19%118
8.26%2
Infinity%