UNPKG

rx-player

Version:
155 lines (154 loc) 5.08 kB
/** * Copyright 2015 CANAL+ Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import log from "../../log"; import { getMDAT } from "../../parsers/containers/isobmff"; import startsWith from "../../utils/starts_with"; import { utf8ToStr } from "../../utils/string_parsing"; /** * Returns the a string expliciting the format of a text track when that text * track is embedded into a ISOBMFF file. * @param {string|undefined} codecs * @returns {string} */ export function getISOBMFFTextTrackFormat(codecs) { if (codecs === undefined) { throw new Error("Cannot parse subtitles: unknown format"); } switch (codecs.toLowerCase()) { case "stpp": // stpp === TTML in MP4 case "stpp.ttml": case "stpp.ttml.im1t": return "ttml"; case "wvtt": // wvtt === WebVTT in MP4 return "vtt"; } throw new Error("The codec used for the subtitles " + `"${codecs}" is not managed yet.`); } /** * Returns the a string expliciting the format of a text track in plain text. * @param {string|undefined} codecs * @param {string|undefined} mimeType * @returns {string} */ export function getPlainTextTrackFormat(codecs, mimeType) { switch (mimeType) { case "application/ttml+xml": return "ttml"; case "application/x-sami": case "application/smil": return "sami"; case "text/vtt": return "vtt"; } if (codecs !== undefined) { const codeLC = codecs.toLowerCase(); if (codeLC === "srt") { return "srt"; } } throw new Error(`could not find a text-track parser for the type ${mimeType !== null && mimeType !== void 0 ? mimeType : ""}`); } /** * @param {Object} content * @param {ArrayBuffer|UInt8Array|null} chunkBytes * @param {number|undefined} initTimescale * @param {Object|null} chunkInfos * @param {boolean} isChunked * @returns {Object|null} */ export function getISOBMFFEmbeddedTextTrackData({ segment, language, codecs, }, chunkBytes, initTimescale, chunkInfos, isChunked) { if (segment.isInit) { return null; } let startTime; let endTime; if (chunkInfos === null) { if (!isChunked) { log.warn("utils", "Unavailable time data for current text track."); } else { startTime = segment.time; endTime = segment.end; } } else { startTime = chunkInfos.time; if (chunkInfos.duration !== undefined) { endTime = startTime + chunkInfos.duration; } else if (!isChunked && segment.complete) { endTime = startTime + segment.duration; } } const type = getISOBMFFTextTrackFormat(codecs); const mdat = getMDAT(chunkBytes); const mdatStr = mdat !== null ? utf8ToStr(mdat) : ""; if (codecs === "wvtt" && !startsWith(mdatStr, "WEBVTT") && !startsWith(mdatStr, "\xfe\xffWEBVTT")) { // From how I understand it, we're here in a special WebVTT format embedded // in an MP4 where the whole chunk contains information, now just the MDAT return { data: chunkBytes, type: "mp4vtt", language, start: startTime, end: endTime, initTimescale: initTimescale !== null && initTimescale !== void 0 ? initTimescale : null, }; } return { data: mdatStr, type, language, start: startTime, end: endTime, initTimescale: initTimescale !== null && initTimescale !== void 0 ? initTimescale : null, }; } /** * @param {Object} context * @param {ArrayBuffer|UInt8Array|null} textTrackData * @param {number|undefined} initTimescale * @param {boolean} isChunked * @returns {Object|null} */ export function getPlainTextTrackData(context, textTrackData, initTimescale, isChunked) { const { segment } = context; if (segment.isInit) { return null; } let start; let end; if (isChunked) { log.warn("utils", "Unavailable time data for current text track."); } else { start = segment.time; if (segment.complete) { end = segment.time + segment.duration; } } const type = getPlainTextTrackFormat(context.codecs, context.mimeType); return { data: textTrackData, type, language: context.language, start, end, initTimescale: initTimescale !== null && initTimescale !== void 0 ? initTimescale : null, }; }