mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-14 15:56:38 +03:00
6e55a3b21b
Fixes #2643 Happy reviewing!
132 lines
3.0 KiB
JavaScript
132 lines
3.0 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.provide('shaka.text.LrcTextParser');
|
|
|
|
goog.require('goog.asserts');
|
|
goog.require('shaka.log');
|
|
goog.require('shaka.text.Cue');
|
|
goog.require('shaka.text.TextEngine');
|
|
goog.require('shaka.util.StringUtils');
|
|
|
|
|
|
/**
|
|
* LRC file format: https://en.wikipedia.org/wiki/LRC_(file_format)
|
|
*
|
|
* @implements {shaka.extern.TextParser}
|
|
* @export
|
|
*/
|
|
shaka.text.LrcTextParser = class {
|
|
/**
|
|
* @override
|
|
* @export
|
|
*/
|
|
parseInit(data) {
|
|
goog.asserts.assert(false, 'LRC does not have init segments');
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @export
|
|
*/
|
|
setSequenceMode(sequenceMode) {
|
|
// Unused.
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @export
|
|
*/
|
|
setManifestType(manifestType) {
|
|
// Unused.
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @export
|
|
*/
|
|
parseMedia(data, time) {
|
|
const StringUtils = shaka.util.StringUtils;
|
|
const LrcTextParser = shaka.text.LrcTextParser;
|
|
|
|
// Get the input as a string.
|
|
const str = StringUtils.fromUTF8(data);
|
|
|
|
/** @type {shaka.text.Cue} */
|
|
let prevCue = null;
|
|
|
|
/** @type {!Array<!shaka.text.Cue>} */
|
|
const cues = [];
|
|
const lines = str.split(/\r?\n/);
|
|
for (const line of lines) {
|
|
if (!line || /^\s+$/.test(line)) {
|
|
continue;
|
|
}
|
|
|
|
// LRC content
|
|
const match = LrcTextParser.lyricLine_.exec(line);
|
|
if (match) {
|
|
const startTime = LrcTextParser.parseTime_(match[1]);
|
|
// This time can be overwritten by a subsequent cue.
|
|
// By default we add 2 seconds of duration.
|
|
const endTime = time.segmentEnd ? time.segmentEnd : startTime + 2;
|
|
const payload = match[2];
|
|
const cue = new shaka.text.Cue(startTime, endTime, payload);
|
|
|
|
// Update previous
|
|
if (prevCue) {
|
|
prevCue.endTime = startTime;
|
|
cues.push(prevCue);
|
|
}
|
|
prevCue = cue;
|
|
continue;
|
|
}
|
|
shaka.log.warning('LrcTextParser encountered an unknown line.', line);
|
|
}
|
|
if (prevCue) {
|
|
cues.push(prevCue);
|
|
}
|
|
|
|
return cues;
|
|
}
|
|
|
|
/**
|
|
* Parses a LRC time from the given parser.
|
|
*
|
|
* @param {string} string
|
|
* @return {number}
|
|
* @private
|
|
*/
|
|
static parseTime_(string) {
|
|
const LrcTextParser = shaka.text.LrcTextParser;
|
|
const match = LrcTextParser.timeFormat_.exec(string);
|
|
const minutes = parseInt(match[1], 10);
|
|
const seconds = parseFloat(match[2].replace(',', '.'));
|
|
return minutes * 60 + seconds;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @const
|
|
* @private {!RegExp}
|
|
* @example [00:12.0]Text or [00:12.00]Text or [00:12.000]Text or
|
|
* [00:12,0]Text or [00:12,00]Text or [00:12,000]Text
|
|
*/
|
|
shaka.text.LrcTextParser.lyricLine_ =
|
|
/^\[(\d{1,2}:\d{1,2}(?:[.,]\d{1,3})?)\](.*)/;
|
|
|
|
/**
|
|
* @const
|
|
* @private {!RegExp}
|
|
* @example 00:12.0 or 00:12.00 or 00:12.000 or
|
|
* 00:12,0 or 00:12,00 or 00:12,000
|
|
*/
|
|
shaka.text.LrcTextParser.timeFormat_ =
|
|
/^(\d+):(\d{1,2}(?:[.,]\d{1,3})?)$/;
|
|
|
|
shaka.text.TextEngine.registerParser(
|
|
'application/x-subtitle-lrc', () => new shaka.text.LrcTextParser());
|