Search code examples
javascriptjsonnode.jssrt

Go through JSON object at specified times (e.g. movie subtitles)


First of all, sorry if the title is not precise enough, if anyone has suggestions they are most welcome. I will explain my problem now. I have a JSON file (although here it's a javascript object), which I want to loop through. It's a subtitle file for a movie, and I would like to show the text precisely like you would expect: only at the times specified.

I am not using a video player or anything else in conjunction with this, so it will only be nodejs going through this file. I do know how I can loop through it with a simple for loop, but I am wondering how to loop through it & do so at exactly the times specified in the respective javascript objects?

 { id: '54',
    startTime: '00:03:46,572',
    endTime: '00:03:53,160',
    text: 'Hello this is a text' 
 },
 { id: '55',
    startTime: '00:03:53,160',
    endTime: '00:03:58,799',
    text: 'To be precise, the subtitle file of a movie' 
 },

Solution

  • First, you must parse your startTime and endTime to milliseconds.

    You can just break the string using the : and , characters, and calculate the milliseconds it represents.

    function parseTime(t) {
        var segments = t.split(':');
        var ms = parseInt(segments[2].split(',')[1]);
        var h = parseInt(segments[0]);
        var m = parseInt(segments[1]);
        var s = parseInt(segments[2]);
        return h * 60 * 60 * 1000 + m * 60 * 1000 + s * 1000 + ms;
    }
    

    Next, go over your array, and transform the times to milliseconds:

    function convertToMs(arr) {
        for (var i = 0; i < arr.length; i++) {
            arr[i].startTime = parseTime(arr[i].startTime);
            arr[i].endTime= parseTime(arr[i].endTime);    
        }
        return arr;
    }
    

    Now, start from the first element in the array, and set a callback to the next element on each call, unless you have reached the end of the array.

    function showSubtitles(arr, i) {
        setTimeout(function() {
            console.log(arr[i].text);
            setTimeout(console.clear, arr[i].endTime - arr[i].startTime); // Make the subtitle "disappear"
            i++;
            if (arr.length > i) {
                showSubtitles(arr, i);
            }
        }, i == 0 ? (arr[i].startTime) : (arr[i].startTime - arr[i-1].startTime));
    }
    

    Now using you array:

    var subtitles = [{
            id: '54',
            startTime: '00:03:46,572',
            endTime: '00:03:53,160',
            text: 'Hello this is a text' 
        },
        { 
            id: '55',
            startTime: '00:03:53,160',
            endTime: '00:03:58,799',
            text: 'To be precise, the subtitle file of a movie' 
        }];
    subtitles = convertToMs(subtitles);
    showSubtitles(subtitles, 0);
    

    Here is a working fiddle, with shorter subtitles timings: https://jsfiddle.net/6oxfx4s1/2/