UNPKG

ts-ebml-esm

Version:
458 lines (457 loc) 12.6 kB
import { Uint64BE as Z, Int64BE as x } from "int64-buffer"; import { tools as W } from "ebml"; import q from "ebml-block"; import G from "matroska-schema"; const { byEbmlID: K } = G; class g { constructor() { this._schema = K, this._buffers = [], this._stack = []; } encode(e) { return m( e.reduce((t, r) => t.concat(this.encodeChunk(r)), []) ).buffer; } encodeChunk(e) { return e.type === "m" ? e.isEnd ? this.endTag(e) : this.startTag(e) : (e.data = Buffer.from(e.data), this.writeTag(e)), this.flush(); } flush() { const e = this._buffers; return this._buffers = [], e; } getSchemaInfo(e) { for (const [t, r] of Object.entries(this._schema)) if (r.name === e) return Buffer.from(Number(t).toString(16), "hex"); return null; } writeTag(e) { const t = e.name, r = this.getSchemaInfo(t), s = e.data; if (r == null) throw new Error("No schema entry found for " + t); const a = E(r, s); if (this._stack.length > 0) { this._stack[this._stack.length - 1].children.push({ tagId: r, elm: e, children: [], data: a }); return; } this._buffers = this._buffers.concat(a); } startTag(e) { const t = e.name, r = this.getSchemaInfo(t); if (r == null) throw new Error("No schema entry found for " + t); if (e.unknownSize) { const a = E(r, Buffer.alloc(0), e.unknownSize); this._buffers = this._buffers.concat(a); return; } const s = { tagId: r, elm: e, children: [], data: null }; this._stack.length > 0 && this._stack[this._stack.length - 1].children.push(s), this._stack.push(s); } endTag(e) { const t = this._stack.pop(); if (t == null) throw new Error("EBML structure is broken"); if (t.elm.name !== e.name) throw new Error("EBML structure is broken"); const r = t.children.reduce((a, f) => { if (f.data === null) throw new Error("EBML structure is broken"); return a.concat(f.data); }, []), s = m(r); t.elm.type === "m" ? t.data = E( t.tagId, s, t.elm.unknownSize ) : t.data = E(t.tagId, s), this._stack.length < 1 && (this._buffers = this._buffers.concat(t.data)); } } const Q = W.readVint, O = W.writeVint, z = q; function X(n) { return z(Buffer.from(n)); } function E(n, e, t = !1) { return m([ n, t ? Buffer.from("01ffffffffffffff", "hex") : O(e.length), e ]); } function Y(n) { return R(n).reduce((e, t) => z(t.data).frames.reduce((s, a) => { const f = j(a), c = new Blob([f], { type: "image/webp" }); return s.concat(c); }, e), []); } function R(n) { return n.reduce((e, t) => t.type !== "b" || t.name !== "SimpleBlock" || !z(t.data).frames.some((a) => a.subarray(3, 6).toString("hex") === "9d012a") ? e : e.concat(t), []); } function j(n) { const e = A("VP8 ", n), t = m([Buffer.from("WEBP", "ascii"), e]); return A("RIFF", t); } function A(n, e) { const t = Buffer.alloc(4); return t.writeUInt32LE(e.byteLength, 0), m([ Buffer.from(n.substring(0, 4), "ascii"), t, e, // padding Buffer.alloc(e.byteLength % 2 === 0 ? 0 : 1) ]); } function ee(n, e, t, r = 0, s = 0) { const a = T("EBML", n), c = k(a) + 12, h = n[n.length - 1].dataEnd - c, l = T( "Info", n ); H("Duration", l), l.splice(1, 0, { name: "Duration", type: "f", data: w(e, 8) }); const _ = k(l), S = T("Tracks", n), p = k(S); let y = 47, o = [], d = 5 + t.length * 15, i = [], B = -1; const b = 10; for (let D = 0; D < b; D++) { const v = y, I = v + _; let P = 0, L = 0; s ? (P = s - c, L = I + p) : (P = I + p, L = P + d); const M = L - h; o = [], o.push({ name: "SeekHead", type: "m", isEnd: !1 }), o.push({ name: "Seek", type: "m", isEnd: !1 }), o.push({ name: "SeekID", type: "b", data: Buffer.from([21, 73, 169, 102]) }), o.push({ name: "SeekPosition", type: "u", data: u(v) }), o.push({ name: "Seek", type: "m", isEnd: !0 }), o.push({ name: "Seek", type: "m", isEnd: !1 }), o.push({ name: "SeekID", type: "b", data: Buffer.from([22, 84, 174, 107]) }), o.push({ name: "SeekPosition", type: "u", data: u(I) }), o.push({ name: "Seek", type: "m", isEnd: !0 }), o.push({ name: "Seek", type: "m", isEnd: !1 }), o.push({ name: "SeekID", type: "b", data: Buffer.from([28, 83, 187, 107]) }), o.push({ name: "SeekPosition", type: "u", data: u(P) }), o.push({ name: "Seek", type: "m", isEnd: !0 }), o.push({ name: "SeekHead", type: "m", isEnd: !0 }), y = k(o), i = [], i.push({ name: "Cues", type: "m", isEnd: !1 }); for (const { CueTrack: $, CueClusterPosition: N, CueTime: J } of t) { i.push({ name: "CuePoint", type: "m", isEnd: !1 }), i.push({ name: "CueTime", type: "u", data: u(J) }), i.push({ name: "CueTrackPositions", type: "m", isEnd: !1 }), i.push({ name: "CueTrack", type: "u", data: u($) }); let F = N - c; r ? F += r : F += M, i.push({ name: "CueClusterPosition", type: "u", data: u(F) }), i.push({ name: "CueTrackPositions", type: "m", isEnd: !0 }), i.push({ name: "CuePoint", type: "m", isEnd: !0 }); } if (i.push({ name: "Cues", type: "m", isEnd: !0 }), d = k(i), B !== M) { if (B = M, D === b - 1) throw new Error("Failed to converge to a stable metadata size"); } else break; } const C = [].concat.apply([], [ a, { name: "Segment", type: "m", isEnd: !1, unknownSize: !0 }, o, l, S, s ? [] : i ]); return new g().encode(C); } function H(n, e) { let t = -1; for (let r = 0; r < e.length; r++) { const s = e[r]; if (s.name === n) if (s.type === "m") if (!s.isEnd) t = r; else { if (t === -1) throw new Error( `Detected ${n} closing element before finding the start` ); e.splice(t, r - t + 1); return; } else { e.splice(r, 1); return; } } } function T(n, e) { let t = [], r = -1; for (let s = 0; s < e.length; s++) { const a = e[s]; if (a.name === n) if (a.type === "m") if (!a.isEnd) r = s; else { if (r === -1) throw new Error( `Detected ${n} closing element before finding the start` ); t = e.slice(r, s + 1); break; } else { t.push(e[s]); break; } } return t; } function te(n, e) { Array.isArray(e.cueInfos) && !Array.isArray(e.cues) && (console.warn( "putRefinedMetaData: info.cueInfos property is deprecated. please use info.cues" ), e.cues = e.cueInfos); let t = [], r = []; for (let o = 0; o < n.length; o++) { const d = n[o]; if (d.type === "m" && d.name === "Segment") { if (t = n.slice(0, o), r = n.slice(o), d.unknownSize) { r.shift(); break; } throw new Error("this metadata is not streaming webm file"); } } if (!(r[r.length - 1].dataEnd > 0)) throw new Error("metadata dataEnd has wrong number"); const s = r[r.length - 1].dataEnd, a = t[t.length - 1].dataEnd, c = new g().encode(t).byteLength - a, h = s - r[0].tagStart, l = Buffer.from([24, 83, 128, 103]), _ = Buffer.from("01ffffffffffffff", "hex"), S = l.byteLength + _.byteLength; let p = h; const y = 20; for (let o = 1; o < y; o++) { const i = a + S + p - s, B = c + i, b = ne(r, B, e), C = new g().encode(b).byteLength; if (C === p) return new g().encode( [].concat( t, [{ type: "m", name: "Segment", isEnd: !1, unknownSize: !0 }], b ) ); p = C; } throw new Error( "unable to refine metadata, stable size could not be found in " + y + " iterations!" ); } function k(n) { const e = new g(); return n.reduce((t, r) => t.concat(e.encode([r])), []).reduce((t, r) => t + r.byteLength, 0); } function ne(n, e, t) { const { duration: r, clusterPtrs: s, cues: a } = t, f = n.slice(0); if (typeof r == "number") { let h = !1; for (const l of f) l.type === "f" && l.name === "Duration" && (h = !0, l.data = w(r, 8)); h || V(f, "Info", [ { name: "Duration", type: "f", data: w(r, 8) } ]); } Array.isArray(a) && V(f, "Cues", se(a, e)); let c = []; return Array.isArray(s) && (console.warn( "append cluster pointers to seekhead is deprecated. please use cues" ), c = re(s, e)), V(f, "SeekHead", c, !0), f; } function re(n, e) { const t = []; for (const r of n) t.push({ name: "Seek", type: "m", isEnd: !1 }), t.push({ name: "SeekID", type: "b", data: Buffer.from([31, 67, 182, 117]) }), t.push({ name: "SeekPosition", type: "u", data: u(r + e) }), t.push({ name: "Seek", type: "m", isEnd: !0 }); return t; } function se(n, e) { const t = []; for (const { CueTrack: r, CueClusterPosition: s, CueTime: a } of n) t.push({ name: "CuePoint", type: "m", isEnd: !1 }), t.push({ name: "CueTime", type: "u", data: u(a) }), t.push({ name: "CueTrackPositions", type: "m", isEnd: !1 }), t.push({ name: "CueTrack", type: "u", data: u(r) }), t.push({ name: "CueClusterPosition", type: "u", data: u(s + e) }), t.push({ name: "CueTrackPositions", type: "m", isEnd: !0 }), t.push({ name: "CuePoint", type: "m", isEnd: !0 }); return t; } function V(n, e, t, r = !1) { let s = -1; for (let a = 0; a < n.length; a++) { const f = n[a]; if (f.type === "m" && f.name === e && !f.isEnd) { s = a; break; } } if (s >= 0) Array.prototype.splice.apply( n, [s + 1, 0].concat(t) ); else if (r) { const a = [].concat( [{ name: e, type: "m", isEnd: !1 }], t, [{ name: e, type: "m", isEnd: !0 }] ); a.reverse(); for (const f of a) n.unshift(f); } else { n.push({ name: e, type: "m", isEnd: !1 }); for (const a of t) n.push(a); n.push({ name: e, type: "m", isEnd: !0 }); } } function m(n) { return Buffer.concat(n); } function ae(n) { let e = Buffer.alloc(0); if (n.type === "m") return n; switch (n.type) { case "u": e = u(n.value); break; case "i": e = U(n.value); break; case "f": e = w(n.value); break; case "s": e = Buffer.from(n.value, "ascii"); break; case "8": e = Buffer.from(n.value, "utf8"); break; case "b": e = n.value; break; case "d": e = new x(n.value.getTime().toString()).toBuffer(); break; } return Object.assign({}, n, { data: e }); } function u(n) { let e = 1; for (; n >= Math.pow(2, 8 * e); e++) ; if (e >= 7) return console.warn("7bit or more bigger uint not supported."), new Z(n).toBuffer(); const t = Buffer.alloc(e); return t.writeUIntBE(n, 0, e), t; } function U(n) { let e = 1; for (; n >= Math.pow(2, 8 * e); e++) ; if (e >= 7) return console.warn("7bit or more bigger uint not supported."), new x(n).toBuffer(); const t = Buffer.alloc(e); return t.writeIntBE(n, 0, e), t; } function w(n, e = 8) { if (e === 8) { const t = Buffer.alloc(8); return t.writeDoubleBE(n, 0), t; } else if (e === 4) { const t = Buffer.alloc(4); return t.writeFloatBE(n, 0), t; } else throw new Error("float type bits must 4bytes or 8bytes"); } function oe(n) { return n instanceof Date ? n : new Date( (/* @__PURE__ */ new Date("2001-01-01T00:00:00.000Z")).getTime() + Number(n) / 1e3 / 1e3 ); } const de = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, VP8BitStreamToRiffWebPBuffer: j, WebPBlockFilter: R, WebPFrameFilter: Y, concat: m, convertEBMLDateToJSDate: oe, createFloatBuffer: w, createIntBuffer: U, createRIFFChunk: A, createUIntBuffer: u, ebmlBlock: z, encodeTag: E, encodeValueToBuffer: ae, extractElement: T, makeMetadataSeekable: ee, putRefinedMetaData: te, readBlock: X, readVint: Q, removeElement: H, writeVint: O }, Symbol.toStringTag, { value: "Module" })); export { g as E, j as V, Y as W, oe as a, X as b, m as c, E as d, z as e, R as f, A as g, H as h, T as i, ae as j, u as k, U as l, ee as m, w as n, te as p, Q as r, de as t, O as w };