Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

frame to SMPTE conversion oddity #2

Open
jedierikb opened this issue Jul 23, 2014 · 5 comments
Open

frame to SMPTE conversion oddity #2

jedierikb opened this issue Jul 23, 2014 · 5 comments

Comments

@jedierikb
Copy link

At 30fps, converting from frames to SMPTE makes a large jump of one hour with a change of one frame:
53999 frames --> 00:29:59:29
54000 frames --> 01:30:00:00

@philippede
Copy link

I found what that bug is:
In .toSMPTE:
Line
var _hours = (frameNumber / _hour).toFixed(0);
Needs to be changed to this:
var _hours = Math.floor(frameNumber / _hour).toFixed(0);

Otherwise, toFixed rounds up to the next hour whenever you pass the 30 minutes mark in a video.

@moxionio
Copy link

Thanks @philippede this fixes the bug!
Doesn't look like this library is maintained anymore as your fix has still not been incorporated into the library...

@czyz
Copy link

czyz commented Feb 5, 2016

More frame to SMPTE math problems. The burned-in timecode in the screenshot starts at 00:59:59:00, so it should be off by a -24 from the frame count of the player.

The VideoFrame library's get() function seems to be grabbing the proper frame count, but video.listen('SMPTE') is off by quite a number of seconds. The video in question is 23.98, and I get the same bad SMPTE values if I set the frameRate to '23.976' or to FrameRates.NTSC_Film.

My code:

        var video = VideoFrame({
            id: 'videoPlayer',
            frameRate: '23.976',
            callback: function(response) {
                $("li.timecode_display").text('TC: '+ response + ' . ');
                $("li.frame_display").text(' ' + 'frame: '+ video.get());
            }
        });

        video.listen('SMPTE');

2016-02-04 at 18 59

@czyz
Copy link

czyz commented Feb 6, 2016

I managed to get this working for 23.976 video by changing VideoFrame.prototype.toTime to use the actual frame rate to calculate the frame number from milliseconds, and then (if the real frame rate is specified as 23.98 or 23.976) to use 24 as the number for calculating SMPTE timecode from the number of frames.

I also added the ability to use an offset to affect displayed timecode values, because my video has a burn-in that reflects its embedded timecode rather than the html5 player's running timecode counter.

I don't know if the changes I made futz things up for frame rates other than a 23.98 variant. This code is working for me, for the moment, but I don't claim to really know what I'm doing as regards either coding or javascript.

VideoFrame.prototype.toTime = function(frames) {
    var time = (typeof frames !== 'number' ? this.video.currentTime : frames), frameRate = this.frameRate;

    var dt = (new Date()), format = 'hh:mm:ss' + (typeof frames === 'number' ? ':ff' : '');
    dt.setHours(0); dt.setMinutes(0); dt.setSeconds(0); dt.setMilliseconds(time * 1000);
    function wrap(n) { return ((n < 10) ? '0' + n : n); } //does double-digit output for numbers
    return format.replace(/hh|mm|ss|ff/g, function(format) {


            //added support for a timecode offset
            var _frameNumber = ((time+(this.video.DisplayOffset/1000))*frameRate);

            //use actual frame rate to determine the number of frames from time, but then use 24fps 
            //to calculate timecode if it's 23.98

            var calcTimeFrameRate = 24;

            switch (frameRate) {
                case "23.98":
                case "23.976": 
                    calcTimeFrameRate = 24; // gotta use 24 to calculate timecodes for 23.98. 
                    break;
                default: 
                    calcTimeFrameRate = frameRate;

            }

            var _hour = ((calcTimeFrameRate * 60) * 60), _minute = (calcTimeFrameRate * 60);

        switch (format) {
            case "hh": return wrap( Math.floor(_frameNumber / _hour).toFixed(0) );
            case "mm": return wrap( (Number((_frameNumber / _minute).toString().split('.')[0]) % 60) );
            case "ss": return wrap( Number((_frameNumber / calcTimeFrameRate).toString().split('.')[0]) % 60);
            case "ff": return wrap( Math.floor(_frameNumber % calcTimeFrameRate) );
        }
    });
};

And for the offset -- up near the top of the code:

var VideoFrame = function(options) {
    if (this === window) { return new VideoFrame(options); }
    this.obj = options || {};
    this.frameRate = this.obj.frameRate || 24;  
    this.video = document.getElementById(this.obj.id) || document.getElementsByTagName('video')[0];

    this.DisplayOffset = this.toMilliseconds(this.obj.TCDisplayOffset) || 0; //Zach added - milliseconds to offset displayed timecode to match burn if embedded TC is different from runtime


};

Less important info, but just to be a completist, here's some other info.

In the html I've got a video and a couple of

  • tags for displaying debugging output while I test this library:

              <li class='timecode_display' id='timecode_display'>Timecode:</li>
              <li class='frame_display' id='frame_display'>Frames:</li>
    

    And down in the javascript, the call to the VideoFrame library to link it up with the inline video and to set the display offset to match the burn-in:

            var video = VideoFrame({
                id: 'videoPlayer',
                frameRate: '23.976',
                TCDisplayOffset: '00:59:59:00',
                callback: function(response) {
    
                    var vid = document.getElementById("videoPlayer");
    
                    $("li.timecode_display").text('TC: '+ response + ' . ');
                    $("li.frame_display").text(' ' + 'frame: '+ video.get() + ' currentTime: '+ vid.currentTime);
                }
            });
    
    
    
  • @JoshuaCWebDeveloper
    Copy link

    My pull request fixes the original bug in this issue. Thanks @philippede for providing the correct solution.

    WesleyE pushed a commit to WesleyE/VideoFrame that referenced this issue Aug 24, 2016
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    None yet
    Projects
    None yet
    Development

    No branches or pull requests

    4 participants