oaprograms / lingo-player

Open source video player with language learning features
MIT License
128 stars 24 forks source link

Extended Subtitle Support #1

Open jaruba opened 9 years ago

jaruba commented 9 years ago

Saw this in the readme:

Support more subtitle formats (currently supports .srt and .sub)

In actuality, wcjs-player supports .srt, .sub and .vtt

I was going to add .ass, .ssa and .txt support based on @vankasteelj 's code but never got to it.

The code itself converts the 3 types mentioned above to .srt, ideally this should be changed to just parse the subs. Hope it helps.

var rl = readline.createInterface({
    input: fs.createReadStream(path.join(origPath, orig)),
    output: process.stdout,
    terminal: false
});
rl.on('line', function (line) {
    //detect encoding
    var charset = charsetDetect.detect(line);
    var encoding = charset.encoding;
    var line_, parsedBeginTime, parsedEndTime, parsedDialog;
    //parse SSA
    if (ext === '.ssa' || ext === '.ass') {
        encoding = 'utf-8';
        if (line.indexOf('Format:') !== -1) {
            var ssaFormat = line.split(',');
            for (var i = 0; i < ssaFormat.length; i++) {
                switch (ssaFormat[i]) {
                    case 'Text':
                    case ' Text':
                         dialog = i;
                         break;
                    case 'Start':
                    case ' Start':
                        begin_time = i;
                        break;
                    case 'End':
                    case ' End':
                        end_time = i;
                        break;
                    default:
                }
            }
            if (dialog && begin_time && end_time) {
                console.debug('SUB formatted in \'ssa\'');
            }
            return; //we have the elms spots, move on to the next line
        }
        if (line.indexOf('Dialogue:') === -1) { //not a dialog line
            return;
        }
        line_ = line.split(',');
        parsedBeginTime = line_[begin_time];
        parsedEndTime = line_[end_time];
        parsedDialog = line_[dialog];
        parsedDialog = parsedDialog.replace('{\\i1}', '<i>').replace('{\\i0}', '</i>'); //italics
        parsedDialog = parsedDialog.replace('{\\b1}', '<b>').replace('{\\b0}', '</b>'); //bold
        parsedDialog = parsedDialog.replace('\\N', '\n'); //return to line
        parsedDialog = parsedDialog.replace(/{.*?}/g, ''); //remove leftovers brackets 
    }
    //parse TXT
    if (ext === '.txt') {
        line_ = line.split('}');
        var formatSeconds = function (seconds) {
            var date = new Date(1970, 0, 1);
            date.setSeconds(seconds);
            return date.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, '$1');
        };
        parsedBeginTime = formatSeconds(line_[0].replace('{', '') / 25);
        parsedEndTime = formatSeconds(line_[1].replace('{', '') / 25);
        parsedDialog = line_[2].replace('|', '\n');
    }
    //SRT needs a number for each subtitle
    counter += 1;
    //keep only the last lang
    if (parsedBeginTime < lastBeginTime) {
        counter = 1;
        fs.writeFileSync(path.join(srtPath, srt), '');
        console.debug('SUB contains multiple tracks, keeping only the last');
    }
    //SRT formatting
    var parsedLine = counter + '\n' + parsedBeginTime + ' --> ' + parsedEndTime + '\n' + parsedDialog;
    fs.appendFileSync(path.join(srtPath, srt), '\n\n' + parsedLine, encoding);
    lastBeginTime = parsedBeginTime;
});
fs.readFile(path.join(srtPath, srt), function (err, dataBuff) {
    if (!err) {
        console.debug('SUB transcoded to SRT:', srt);
        callback(dataBuff);
    } else {
        console.warn('SUB transcoding failed', err);
    }
});
vankasteelj commented 9 years ago

It turns ASS:

Dialogue: 0,1:48:28.18,1:48:29.66,Default,,0,0,0,,- C'est tellement politique...

into SRT:

285
1:48:28.18 --> 1:48:29.66
- C'est tellement politique...

Note that charsetDetect = require('jschardet');

You probably can better understand what it does by adding those at the end of the rl.on('line', function (line) {}) function:

console.log(line)
console.log(parsedLine)

You'll also find the entire code there: https://gist.github.com/vankasteelj/39723be4a99fc2d151b1

It is crappy and needs serious rewrite, but I scavenged that from popcorntime and found it useful, although I have nor the time nor the will to rewrite it or deeply analyze it.

oaprograms commented 8 years ago

Thanks. Somebody should merge all of these into a library. Though I also don't have the time for that now...

le-wei commented 6 years ago

wcjs-player is it possible to pass subtitles pass vlc,the method used vlc resolution subtitles. like var player=[{ url:"file:///D:/1.mp4", vlcArgs:":sub-file=D:/2.ass" }]

le-wei commented 6 years ago

Play local video, there is a subtitle with the same name as the video and subtitle files and video files in the same directory, vlc can automatically load ass file