diff --git a/Cargo.lock b/Cargo.lock
index e75d3e8..07324ab 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,24 +2,75 @@
# It is not intended for manual editing.
version = 4
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+[[package]]
+name = "bindgen"
+version = "0.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
+dependencies = [
+ "bitflags 2.9.0",
+ "cexpr",
+ "clang-sys",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "syn",
+]
+
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+[[package]]
+name = "bitflags"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+
[[package]]
name = "bytemuck"
version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
+[[package]]
+name = "cc"
+version = "1.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom",
+]
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -27,12 +78,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
-name = "demuxing"
-version = "0.1.0"
+name = "clang-sys"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
- "symphonia-format-mkv",
+ "glob",
+ "libc",
+ "libloading",
]
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
[[package]]
name = "encoding_rs"
version = "0.8.35"
@@ -42,18 +103,180 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "ffmpeg-sys-next"
+version = "7.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bc3234d0a4b2f7d083699d0860c6c9dd83713908771b60f94a96f8704adfe45"
+dependencies = [
+ "bindgen",
+ "cc",
+ "libc",
+ "num_cpus",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "konoplayer-codecs"
+version = "0.1.0"
+dependencies = [
+ "ffmpeg-sys-next",
+]
+
+[[package]]
+name = "konoplayer-demuxing"
+version = "0.1.0"
+dependencies = [
+ "symphonia-format-mkv",
+]
+
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+[[package]]
+name = "libc"
+version = "0.2.171"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
+
+[[package]]
+name = "libloading"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
+dependencies = [
+ "cfg-if",
+ "windows-targets",
+]
+
[[package]]
name = "log"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
[[package]]
name = "symphonia-core"
version = "0.5.4"
@@ -61,7 +284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3"
dependencies = [
"arrayvec",
- "bitflags",
+ "bitflags 1.3.2",
"bytemuck",
"lazy_static",
"log",
@@ -101,3 +324,90 @@ dependencies = [
"symphonia-core",
"symphonia-metadata",
]
+
+[[package]]
+name = "syn"
+version = "2.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/Cargo.toml b/Cargo.toml
index caef8b4..93842e9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,3 @@
[workspace]
-members = ["packages/demuxing"]
-resolver = "2"
+members = ["packages/demuxing", "packages/codecs"]
+resolver = "3"
diff --git a/apps/mock/.gitignore b/apps/mock/.gitignore
index 1eed71a..bc0cfa4 100644
--- a/apps/mock/.gitignore
+++ b/apps/mock/.gitignore
@@ -1 +1,2 @@
-public/video-sample/huge/*
\ No newline at end of file
+public/video/huge/*
+!public/video/huge/.gitkeep
\ No newline at end of file
diff --git a/apps/mock/public/video-sample/audiosample.webm b/apps/mock/public/video/audiosample.webm
similarity index 100%
rename from apps/mock/public/video-sample/audiosample.webm
rename to apps/mock/public/video/audiosample.webm
diff --git a/apps/mock/public/video/huge/.gitkeep b/apps/mock/public/video/huge/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/apps/mock/public/video-sample/test.webm b/apps/mock/public/video/test.webm
similarity index 100%
rename from apps/mock/public/video-sample/test.webm
rename to apps/mock/public/video/test.webm
diff --git a/apps/mock/public/video-sample/video-webm-codecs-avc1-42E01E.webm b/apps/mock/public/video/video-webm-codecs-avc1-42E01E.webm
similarity index 100%
rename from apps/mock/public/video-sample/video-webm-codecs-avc1-42E01E.webm
rename to apps/mock/public/video/video-webm-codecs-avc1-42E01E.webm
diff --git a/apps/mock/public/video-sample/video-webm-codecs-vp8.webm b/apps/mock/public/video/video-webm-codecs-vp8.webm
similarity index 100%
rename from apps/mock/public/video-sample/video-webm-codecs-vp8.webm
rename to apps/mock/public/video/video-webm-codecs-vp8.webm
diff --git a/apps/playground/package.json b/apps/playground/package.json
index 452f9c1..e8b69bc 100644
--- a/apps/playground/package.json
+++ b/apps/playground/package.json
@@ -9,7 +9,7 @@
"preview": "rsbuild preview"
},
"dependencies": {
- "konoebml": "0.1.1",
+ "konoebml": "0.1.2-rc.5",
"lit": "^3.2.1"
},
"devDependencies": {
diff --git a/apps/playground/src/fetch.ts b/apps/playground/src/fetch.ts
index 4570150..4ff4a9f 100644
--- a/apps/playground/src/fetch.ts
+++ b/apps/playground/src/fetch.ts
@@ -5,11 +5,17 @@ export interface RangedStream {
totalSize?: number;
}
-export async function createRangedStream(
- url: string,
+export interface CreateRangedStreamOptions {
+ url: string;
+ byteStart?: number;
+ byteEnd?: number;
+}
+
+export async function createRangedStream({
+ url,
byteStart = 0,
- byteEnd?: number
-) {
+ byteEnd,
+}: CreateRangedStreamOptions) {
const controller = new AbortController();
const signal = controller.signal;
const headers = new Headers();
diff --git a/apps/playground/src/index.html b/apps/playground/src/index.html
index 8a54361..a31a7ed 100644
--- a/apps/playground/src/index.html
+++ b/apps/playground/src/index.html
@@ -4,6 +4,6 @@
-
-
+
+
\ No newline at end of file
diff --git a/apps/playground/src/media/mkv/model.ts b/apps/playground/src/media/mkv/model.ts
index 42ce80a..b2ea239 100644
--- a/apps/playground/src/media/mkv/model.ts
+++ b/apps/playground/src/media/mkv/model.ts
@@ -8,13 +8,15 @@ import {
type EbmlSegmentTagType,
EbmlTagIdEnum,
EbmlTagPosition,
+ EbmlTagsTagType,
+ EbmlTagTagType,
type EbmlTagType,
type EbmlTrackEntryTagType,
type EbmlTracksTagType,
} from 'konoebml';
-import {convertEbmlTagToComponent, type InferType,} from './util';
-import {isEqual, maxBy} from 'lodash-es';
-import {ArkErrors, type Type} from 'arktype';
+import { convertEbmlTagToComponent, type InferType } from './util';
+import { isEqual, maxBy } from 'lodash-es';
+import { ArkErrors, type Type } from 'arktype';
import {
ClusterSchema,
type ClusterType,
@@ -25,13 +27,16 @@ import {
type InfoType,
SeekHeadSchema,
type SeekHeadType,
+ TagSchema,
+ TagType,
TrackEntrySchema,
- type TrackEntryType
+ type TrackEntryType,
} from './schema';
export const SEEK_ID_KAX_INFO = new Uint8Array([0x15, 0x49, 0xa9, 0x66]);
export const SEEK_ID_KAX_TRACKS = new Uint8Array([0x16, 0x54, 0xae, 0x6b]);
export const SEEK_ID_KAX_CUES = new Uint8Array([0x1c, 0x53, 0xbb, 0x6b]);
+export const SEEK_ID_KAX_TAGS = new Uint8Array([0x12, 0x54, 0xc3, 0x67]);
export class SegmentSystem {
startTag: EbmlSegmentTagType;
@@ -42,7 +47,7 @@ export class SegmentSystem {
seek: SeekSystem;
info: InfoSystem;
track: TrackSystem;
-
+ tag: TagSystem;
constructor(startNode: EbmlSegmentTagType) {
this.startTag = startNode;
@@ -51,23 +56,25 @@ export class SegmentSystem {
this.seek = new SeekSystem(this);
this.info = new InfoSystem(this);
this.track = new TrackSystem(this);
+ this.tag = new TagSystem(this);
}
- get dataStartOffset() {
+ get contentStartOffset() {
return this.startTag.startOffset + this.startTag.headerLength;
}
- get startOffset () {
+ get startOffset() {
return this.startTag.startOffset;
}
- completeHeads () {
+ completeHeads() {
const infoTag = this.seek.seekTagBySeekId(SEEK_ID_KAX_INFO);
const tracksTag = this.seek.seekTagBySeekId(SEEK_ID_KAX_TRACKS);
const cuesTag = this.seek.seekTagBySeekId(SEEK_ID_KAX_CUES);
+ const tagsTag = this.seek.seekTagBySeekId(SEEK_ID_KAX_TAGS);
if (cuesTag?.id === EbmlTagIdEnum.Cues) {
- this.cue.prepareCuesWithTag(cuesTag)
+ this.cue.prepareCuesWithTag(cuesTag);
}
if (infoTag?.id === EbmlTagIdEnum.Info) {
this.info.prepareWithInfoTag(infoTag);
@@ -75,11 +82,14 @@ export class SegmentSystem {
if (tracksTag?.id === EbmlTagIdEnum.Tracks) {
this.track.prepareTracksWithTag(tracksTag);
}
+ if (tagsTag?.id === EbmlTagIdEnum.Tags) {
+ this.tag.prepareTagsWIthTag(tagsTag);
+ }
return this;
}
- scanHead (tag: EbmlTagType) {
+ scanHead(tag: EbmlTagType) {
if (
tag.id === EbmlTagIdEnum.SeekHead &&
tag.position === EbmlTagPosition.End
@@ -92,30 +102,56 @@ export class SegmentSystem {
}
}
-export class SegmentComponentSystemTrait> {
+export type SegmentComponent = T & {
+ get segment(): SegmentSystem;
+};
+
+export function withSegment(
+ component: T,
+ segment: SegmentSystem
+): SegmentComponent {
+ const component_ = component as T & { segment: SegmentSystem };
+ component_.segment = segment;
+ return component_;
+}
+
+export class SegmentComponentSystemTrait<
+ E extends EbmlMasterTagType,
+ S extends Type,
+> {
segment: SegmentSystem;
get schema(): S {
- throw new Error("unimplemented!")
+ throw new Error('unimplemented!');
}
constructor(segment: SegmentSystem) {
this.segment = segment;
}
- componentFromTag(tag: E): InferType {
+ componentFromTag(tag: E): SegmentComponent> {
const extracted = convertEbmlTagToComponent(tag);
- const result = this.schema(extracted);
+ const result = this.schema(extracted) as
+ | (InferType & { segment: SegmentSystem })
+ | ArkErrors;
if (result instanceof ArkErrors) {
const errors = result;
- console.error('Parse component from tag error:', tag.toDebugRecord(), errors.flatProblemsByPath)
+ console.error(
+ 'Parse component from tag error:',
+ tag.toDebugRecord(),
+ errors.flatProblemsByPath
+ );
throw errors;
}
- return result as InferType
+ result.segment = this.segment;
+ return result;
}
}
-export class SeekSystem extends SegmentComponentSystemTrait {
+export class SeekSystem extends SegmentComponentSystemTrait<
+ EbmlSeekHeadTagType,
+ typeof SeekHeadSchema
+> {
override get schema() {
return SeekHeadSchema;
}
@@ -123,25 +159,21 @@ export class SeekSystem extends SegmentComponentSystemTrait = new Map();
- memoTag (tag: EbmlTagType) {
+ memoTag(tag: EbmlTagType) {
this.offsetToTagMemo.set(tag.startOffset, tag);
}
- addSeekHeadTag (tag: EbmlSeekHeadTagType) {
+ addSeekHeadTag(tag: EbmlSeekHeadTagType) {
const seekHead = this.componentFromTag(tag);
this.seekHeads.push(seekHead);
return seekHead;
}
- offsetFromSeekPosition (position: number): number {
- return position + this.segment.startOffset;
+ offsetFromSeekPosition(position: number): number {
+ return position + this.segment.contentStartOffset;
}
- offsetFromSeekDataPosition (position: number) : number {
- return position + this.segment.dataStartOffset;
- }
-
- seekTagByStartOffset (
+ seekTagByStartOffset(
startOffset: number | undefined
): EbmlTagType | undefined {
return startOffset! >= 0
@@ -150,60 +182,80 @@ export class SeekSystem extends SegmentComponentSystemTrait isEqual(c.SeekID, seekId))
- ?.SeekPosition;
- return seekPosition! >= 0 ? this.offsetFromSeekPosition(seekPosition!) : undefined;
+ const seekPosition = this.seekHeads[0]?.Seek?.find((c) =>
+ isEqual(c.SeekID, seekId)
+ )?.SeekPosition;
+ return seekPosition! >= 0
+ ? this.offsetFromSeekPosition(seekPosition! as number)
+ : undefined;
}
seekTagBySeekId(seekId: Uint8Array): EbmlTagType | undefined {
- return this.seekTagByStartOffset(
- this.seekOffsetBySeekId(seekId)
- );
+ return this.seekTagByStartOffset(this.seekOffsetBySeekId(seekId));
}
}
-export class InfoSystem extends SegmentComponentSystemTrait {
+export class InfoSystem extends SegmentComponentSystemTrait<
+ EbmlInfoTagType,
+ typeof InfoSchema
+> {
override get schema() {
return InfoSchema;
}
- info!: InfoType;
+ info!: SegmentComponent;
- prepareWithInfoTag (tag: EbmlInfoTagType) {
+ prepareWithInfoTag(tag: EbmlInfoTagType) {
this.info = this.componentFromTag(tag);
return this;
}
}
-export class ClusterSystem extends SegmentComponentSystemTrait {
+export class ClusterSystem extends SegmentComponentSystemTrait<
+ EbmlClusterTagType,
+ typeof ClusterSchema
+> {
override get schema() {
- return ClusterSchema
+ return ClusterSchema;
}
- clustersBuffer: ClusterType[] = [];
+ clustersBuffer: SegmentComponent[] = [];
- addClusterWithTag (tag: EbmlClusterTagType): ClusterType {
+ addClusterWithTag(tag: EbmlClusterTagType) {
const cluster = this.componentFromTag(tag);
this.clustersBuffer.push(cluster);
return cluster;
}
}
-export class TrackSystem extends SegmentComponentSystemTrait {
+export class TrackSystem extends SegmentComponentSystemTrait<
+ EbmlTrackEntryTagType,
+ typeof TrackEntrySchema
+> {
override get schema() {
return TrackEntrySchema;
}
- tracks = new Map();
+ tracks: SegmentComponent[] = [];
- prepareTracksWithTag (tag: EbmlTracksTagType) {
- this.tracks.clear();
- for (const c of tag.children) {
- if (c.id === EbmlTagIdEnum.TrackEntry) {
- const trackEntry = this.componentFromTag(c);
- this.tracks.set(trackEntry.TrackNumber, trackEntry);
- }
- }
+ getTrackEntry({
+ priority = (track) =>
+ (Number(!!track.FlagForced) << 4) + Number(!!track.FlagDefault),
+ predicate = (track) => track.FlagEnabled !== 0,
+ }: {
+ priority?: (v: SegmentComponent) => number;
+ predicate?: (v: SegmentComponent) => boolean;
+ }) {
+ return this.tracks
+ .filter(predicate)
+ .toSorted((a, b) => priority(b) - priority(a))
+ .at(0);
+ }
+
+ prepareTracksWithTag(tag: EbmlTracksTagType) {
+ this.tracks = tag.children
+ .filter((c) => c.id === EbmlTagIdEnum.TrackEntry)
+ .map((c) => this.componentFromTag(c));
return this;
}
}
@@ -212,16 +264,15 @@ export class CueSystem extends SegmentComponentSystemTrait<
EbmlCuePointTagType,
typeof CuePointSchema
> {
- override get schema () {
- return CuePointSchema
- };
+ override get schema() {
+ return CuePointSchema;
+ }
- cues: CuePointType[] = [];
+ cues: SegmentComponent[] = [];
-
- prepareCuesWithTag (tag: EbmlCuesTagType) {
+ prepareCuesWithTag(tag: EbmlCuesTagType) {
this.cues = tag.children
- .filter(c => c.id === EbmlTagIdEnum.CuePoint)
+ .filter((c) => c.id === EbmlTagIdEnum.CuePoint)
.map(this.componentFromTag.bind(this));
return this;
}
@@ -259,24 +310,54 @@ export class CueSystem extends SegmentComponentSystemTrait<
const before = cues[right];
const after = cues[left];
- return Math.abs(before.CueTime - seekTime) <
- Math.abs(after.CueTime - seekTime)
+ return Math.abs((before.CueTime as number) - seekTime) <
+ Math.abs((after.CueTime as number) - seekTime)
? before
: after;
}
- getCueTrackPositions (cuePoint: CuePointType, track?: number): CueTrackPositionsType {
+ getCueTrackPositions(
+ cuePoint: CuePointType,
+ track?: number
+ ): CueTrackPositionsType {
let cueTrackPositions: CueTrackPositionsType | undefined;
if (track! >= 0) {
- cueTrackPositions = cuePoint.CueTrackPositions.find(c => c.CueTrack === track);
+ cueTrackPositions = cuePoint.CueTrackPositions.find(
+ (c) => c.CueTrack === track
+ );
}
- if (!cueTrackPositions) {
- cueTrackPositions = maxBy(cuePoint.CueTrackPositions, c => c.CueClusterPosition)!;
- }
- return cueTrackPositions;
+ if (!cueTrackPositions) {
+ cueTrackPositions = maxBy(
+ cuePoint.CueTrackPositions,
+ (c) => c.CueClusterPosition
+ )!;
+ }
+ return cueTrackPositions;
}
- get prepared (): boolean {
+ get prepared(): boolean {
return this.cues.length > 0;
}
}
+
+export class TagSystem extends SegmentComponentSystemTrait<
+ EbmlTagTagType,
+ typeof TagSchema
+> {
+ override get schema() {
+ return TagSchema;
+ }
+
+ tags: SegmentComponent[] = [];
+
+ prepareWithTagsTag(tag: EbmlTagsTagType) {
+ this.tags = tag.children
+ .filter((c) => c.id === EbmlTagIdEnum.Tag)
+ .map((c) => this.componentFromTag(c));
+ return this;
+ }
+
+ get prepared(): boolean {
+ return this.tags.length > 0;
+ }
+}
diff --git a/apps/playground/src/media/mkv/reactive.ts b/apps/playground/src/media/mkv/reactive.ts
index 9b630a7..de0d117 100644
--- a/apps/playground/src/media/mkv/reactive.ts
+++ b/apps/playground/src/media/mkv/reactive.ts
@@ -25,23 +25,32 @@ import {
takeUntil,
withLatestFrom,
} from 'rxjs';
-import { createRangedStream } from '@/fetch';
-import { SegmentSystem, SEEK_ID_KAX_CUES, type CueSystem } from './model';
-import { isTagIdPos } from './util';
-import type { ClusterType } from "./schema";
+import { createRangedStream, type CreateRangedStreamOptions } from '@/fetch';
+import {
+ SegmentSystem,
+ SEEK_ID_KAX_CUES,
+ type CueSystem,
+ type SegmentComponent,
+ SEEK_ID_KAX_TAGS,
+} from './model';
+import { isTagIdPos, waitTick } from './util';
+import type { ClusterType } from './schema';
-export function createRangedEbmlStream(
- url: string,
+export interface CreateRangedEbmlStreamOptions
+ extends CreateRangedStreamOptions {}
+
+export function createRangedEbmlStream({
+ url,
byteStart = 0,
- byteEnd?: number
-): Observable<{
+ byteEnd,
+}: CreateRangedEbmlStreamOptions): Observable<{
ebml$: Observable;
totalSize?: number;
response: Response;
body: ReadableStream;
controller: AbortController;
}> {
- const stream$ = from(createRangedStream(url, byteStart, byteEnd));
+ const stream$ = from(createRangedStream({ url, byteStart, byteEnd }));
return stream$.pipe(
switchMap(({ controller, body, totalSize, response }) => {
@@ -52,13 +61,20 @@ export function createRangedEbmlStream(
new EbmlStreamDecoder({
streamStartOffset: byteStart,
collectChild: (child) => child.id !== EbmlTagIdEnum.Cluster,
+ backpressure: {
+ eventLoop: waitTick,
+ },
})
)
.pipeTo(
new WritableStream({
- write: (tag) => subscriber.next(tag),
+ write: async (tag) => {
+ await waitTick();
+ subscriber.next(tag);
+ },
close: () => {
if (!requestCompleted) {
+ requestCompleted = true;
subscriber.complete();
}
},
@@ -68,6 +84,7 @@ export function createRangedEbmlStream(
if (requestCompleted && error?.name === 'AbortError') {
return;
}
+ requestCompleted = true;
subscriber.error(error);
});
@@ -103,8 +120,19 @@ export function createRangedEbmlStream(
})
);
}
-export function createEbmlController(src: string) {
- const request$ = createRangedEbmlStream(src, 0);
+
+export interface CreateEbmlControllerOptions
+ extends Omit {}
+
+export function createEbmlController({
+ url,
+ ...options
+}: CreateEbmlControllerOptions) {
+ const request$ = createRangedEbmlStream({
+ ...options,
+ url,
+ byteStart: 0,
+ });
const controller$ = request$.pipe(
map(({ totalSize, ebml$, response, controller }) => {
@@ -115,7 +143,7 @@ export function createEbmlController(src: string) {
);
console.debug(
- `stream of video "${src}" created, total size is ${totalSize ?? 'unknown'}`
+ `stream of video "${url}" created, total size is ${totalSize ?? 'unknown'}`
);
const segmentStart$ = ebml$.pipe(
@@ -123,18 +151,16 @@ export function createEbmlController(src: string) {
filter((tag) => tag.id === EbmlTagIdEnum.Segment)
);
+ /**
+ * while [matroska v4](https://www.matroska.org/technical/elements.html) doc tell that there is only one segment in a file
+ * some mkv generated by strange tools will emit several
+ */
const segments$ = segmentStart$.pipe(
map((startTag) => {
const segment = new SegmentSystem(startTag);
const clusterSystem = segment.cluster;
const seekSystem = segment.seek;
- const continuousReusedCluster$ = ebml$.pipe(
- filter(isTagIdPos(EbmlTagIdEnum.Cluster, EbmlTagPosition.End)),
- filter((s) => s.id === EbmlTagIdEnum.Cluster),
- map(clusterSystem.addClusterWithTag.bind(clusterSystem))
- );
-
const segmentEnd$ = ebml$.pipe(
filter(isTagIdPos(EbmlTagIdEnum.Segment, EbmlTagPosition.End)),
filter((tag) => tag.id === EbmlTagIdEnum.Segment),
@@ -170,9 +196,14 @@ export function createEbmlController(src: string) {
if (cueSystem.prepared) {
return EMPTY;
}
- const remoteCuesTagStartOffset = seekSystem.seekOffsetBySeekId(SEEK_ID_KAX_CUES);
+ const remoteCuesTagStartOffset =
+ seekSystem.seekOffsetBySeekId(SEEK_ID_KAX_CUES);
if (remoteCuesTagStartOffset! >= 0) {
- return createRangedEbmlStream(src, remoteCuesTagStartOffset).pipe(
+ return createRangedEbmlStream({
+ ...options,
+ url,
+ byteStart: remoteCuesTagStartOffset,
+ }).pipe(
switchMap((req) => req.ebml$),
filter(isTagIdPos(EbmlTagIdEnum.Cues, EbmlTagPosition.End)),
withLatestFrom(withMeta$),
@@ -189,7 +220,42 @@ export function createEbmlController(src: string) {
);
const withLocalCues$ = withMeta$.pipe(
- switchMap((s) => s.cue.prepared ? of(s) : EMPTY),
+ switchMap((s) => (s.cue.prepared ? of(s) : EMPTY)),
+ shareReplay(1)
+ );
+
+ const withRemoteTags$ = withMeta$.pipe(
+ switchMap((s) => {
+ const tagSystem = s.tag;
+ const seekSystem = s.seek;
+ if (tagSystem.prepared) {
+ return EMPTY;
+ }
+ const remoteTagsTagStartOffset =
+ seekSystem.seekOffsetBySeekId(SEEK_ID_KAX_TAGS);
+ if (remoteTagsTagStartOffset! >= 0) {
+ return createRangedEbmlStream({
+ ...options,
+ url,
+ byteStart: remoteTagsTagStartOffset,
+ }).pipe(
+ switchMap((req) => req.ebml$),
+ filter(isTagIdPos(EbmlTagIdEnum.Tags, EbmlTagPosition.End)),
+ withLatestFrom(withMeta$),
+ map(([tags, withMeta]) => {
+ withMeta.tag.prepareWithTagsTag(tags);
+ return withMeta;
+ })
+ );
+ }
+ return EMPTY;
+ }),
+ take(1),
+ shareReplay(1)
+ );
+
+ const withLocalTags$ = withMeta$.pipe(
+ switchMap((s) => (s.tag.prepared ? of(s) : EMPTY)),
shareReplay(1)
);
@@ -202,24 +268,33 @@ export function createEbmlController(src: string) {
switchMap((empty) => (empty ? withMeta$ : EMPTY))
);
- const seekWithoutCues = (seekTime: number): Observable => {
- const cluster$ = continuousReusedCluster$.pipe(
- isEmpty(),
- switchMap((empty) => {
- return empty
- ? clusterStart$.pipe(
- switchMap((startTag) =>
- createRangedEbmlStream(src, startTag.startOffset)
- ),
- switchMap((req) => req.ebml$),
- filter(
- isTagIdPos(EbmlTagIdEnum.Cluster, EbmlTagPosition.End)
- ),
- map((tag) => clusterSystem.addClusterWithTag(tag))
- )
- : continuousReusedCluster$;
- })
+ const withTags$ = merge(withLocalTags$, withRemoteTags$).pipe(
+ take(1)
+ );
+
+ const withoutTags$ = withTags$.pipe(
+ isEmpty(),
+ switchMap((empty) => (empty ? withMeta$ : EMPTY))
+ );
+
+ const seekWithoutCues = (
+ seekTime: number
+ ): Observable> => {
+ const request$ = clusterStart$.pipe(
+ switchMap((startTag) =>
+ createRangedEbmlStream({
+ ...options,
+ url,
+ byteStart: startTag.startOffset,
+ })
+ )
);
+ const cluster$ = request$.pipe(
+ switchMap((req) => req.ebml$),
+ filter(isTagIdPos(EbmlTagIdEnum.Cluster, EbmlTagPosition.End)),
+ map((tag) => clusterSystem.addClusterWithTag(tag))
+ );
+
if (seekTime === 0) {
return cluster$;
}
@@ -228,12 +303,12 @@ export function createEbmlController(src: string) {
scan(
(prev, curr) =>
[prev?.[1], curr] as [
- ClusterType | undefined,
- ClusterType | undefined,
+ SegmentComponent | undefined,
+ SegmentComponent | undefined,
],
[undefined, undefined] as [
- ClusterType | undefined,
- ClusterType | undefined,
+ SegmentComponent | undefined,
+ SegmentComponent | undefined,
]
),
filter((c) => c[1]?.Timestamp! > seekTime),
@@ -242,30 +317,36 @@ export function createEbmlController(src: string) {
};
const seekWithCues = (
- cues: CueSystem,
+ cueSystem: CueSystem,
seekTime: number
- ): Observable => {
+ ): Observable> => {
if (seekTime === 0) {
return seekWithoutCues(seekTime);
}
- const cuePoint = cues.findClosestCue(seekTime);
+ const cuePoint = cueSystem.findClosestCue(seekTime);
if (!cuePoint) {
return seekWithoutCues(seekTime);
}
- return createRangedEbmlStream(
- src,
- seekSystem.offsetFromSeekDataPosition(cues.getCueTrackPositions(cuePoint).CueClusterPosition)
- ).pipe(
+ return createRangedEbmlStream({
+ ...options,
+ url,
+ byteStart: seekSystem.offsetFromSeekPosition(
+ cueSystem.getCueTrackPositions(cuePoint)
+ .CueClusterPosition as number
+ ),
+ }).pipe(
switchMap((req) => req.ebml$),
filter(isTagIdPos(EbmlTagIdEnum.Cluster, EbmlTagPosition.End)),
map(clusterSystem.addClusterWithTag.bind(clusterSystem))
);
};
- const seek = (seekTime: number): Observable => {
+ const seek = (
+ seekTime: number
+ ): Observable> => {
if (seekTime === 0) {
const subscription = merge(withCues$, withoutCues$).subscribe();
@@ -277,11 +358,7 @@ export function createEbmlController(src: string) {
);
}
return merge(
- withCues$.pipe(
- switchMap((s) =>
- seekWithCues(s.cue, seekTime)
- )
- ),
+ withCues$.pipe(switchMap((s) => seekWithCues(s.cue, seekTime))),
withoutCues$.pipe(switchMap((_) => seekWithoutCues(seekTime)))
);
};
@@ -294,6 +371,8 @@ export function createEbmlController(src: string) {
withMeta$,
withCues$,
withoutCues$,
+ withTags$,
+ withoutTags$,
seekWithCues,
seekWithoutCues,
seek,
@@ -309,7 +388,8 @@ export function createEbmlController(src: string) {
controller,
response,
};
- })
+ }),
+ shareReplay(1)
);
return {
diff --git a/apps/playground/src/media/mkv/schema.ts b/apps/playground/src/media/mkv/schema.ts
index 1a84ffd..e75d524 100644
--- a/apps/playground/src/media/mkv/schema.ts
+++ b/apps/playground/src/media/mkv/schema.ts
@@ -1,5 +1,5 @@
import { type, match } from 'arktype';
-import { EbmlTagIdEnum, EbmlSimpleBlockTag ,EbmlBlockTag } from 'konoebml';
+import { EbmlTagIdEnum, EbmlSimpleBlockTag, EbmlBlockTag } from 'konoebml';
export const BinarySchema = type.instanceOf(Uint8Array);
export const SimpleBlockSchema = type.instanceOf(EbmlSimpleBlockTag);
@@ -7,19 +7,19 @@ export const BlockSchema = type.instanceOf(EbmlBlockTag);
export const DocTypeExtensionSchema = type({
DocTypeExtensionName: type.string,
- DocTypeExtensionVersion: type.number,
+ DocTypeExtensionVersion: type.number.or(type.bigint),
});
export type DocTypeExtensionType = typeof DocTypeExtensionSchema.infer;
export const EBMLSchema = type({
- EBMLVersion: type.number.default(1),
- EBMLReadVersion: type.number.default(1),
- EBMLMaxIDLength: type.number.default(4),
- EBMLMaxSizeLength: type.number.default(8),
+ EBMLVersion: type.number.or(type.bigint).default(1),
+ EBMLReadVersion: type.number.or(type.bigint).default(1),
+ EBMLMaxIDLength: type.number.or(type.bigint).default(4),
+ EBMLMaxSizeLength: type.number.or(type.bigint).default(8),
DocType: type.string,
- DocTypeVersion: type.number.default(1),
- DocTypeReadVersion: type.number.default(1),
+ DocTypeVersion: type.number.or(type.bigint).default(1),
+ DocTypeReadVersion: type.number.or(type.bigint).default(1),
DocTypeExtension: DocTypeExtensionSchema.array().optional(),
});
@@ -27,7 +27,7 @@ export type EBMLType = typeof EBMLSchema.infer;
export const SeekSchema = type({
SeekID: BinarySchema,
- SeekPosition: type.number,
+ SeekPosition: type.number.or(type.bigint),
});
export type SeekType = typeof SeekSchema.infer;
@@ -40,8 +40,8 @@ export type SeekHeadType = typeof SeekHeadSchema.infer;
export const ChapterTranslateSchema = type({
ChapterTranslateID: BinarySchema,
- ChapterTranslateCodec: type.number,
- ChapterTranslateEditionUID: type.number.array().optional(),
+ ChapterTranslateCodec: type.number.or(type.bigint),
+ ChapterTranslateEditionUID: type.number.or(type.bigint).array().optional(),
});
export type ChapterTranslateType = typeof ChapterTranslateSchema.infer;
@@ -55,7 +55,7 @@ export const InfoSchema = type({
NextFilename: type.string.optional(),
SegmentFamily: BinarySchema.array().optional(),
ChapterTranslate: ChapterTranslateSchema.array().optional(),
- TimestampScale: type.number.default(1000000),
+ TimestampScale: type.number.or(type.bigint).default(1000000),
Duration: type.number.optional(),
DateUTC: BinarySchema.optional(),
Title: type.string.optional(),
@@ -66,14 +66,14 @@ export const InfoSchema = type({
export type InfoType = typeof InfoSchema.infer;
export const SilentTracksSchema = type({
- SilentTrackNumber: type.number.array().optional(),
+ SilentTrackNumber: type.number.or(type.bigint).array().optional(),
});
export type SilentTracksType = typeof SilentTracksSchema.infer;
export const BlockMoreSchema = type({
BlockAdditional: BinarySchema,
- BlockAddID: type.number.default(1),
+ BlockAddID: type.number.or(type.bigint).default(1),
});
export type BlockMoreType = typeof BlockMoreSchema.infer;
@@ -85,11 +85,11 @@ export const BlockAdditionsSchema = type({
export type BlockAdditionsType = typeof BlockAdditionsSchema.infer;
export const TimeSliceSchema = type({
- LaceNumber: type.number.optional(),
- FrameNumber: type.number.default(0),
- BlockAdditionID: type.number.default(0),
- Delay: type.number.default(0),
- SliceDuration: type.number.default(0),
+ LaceNumber: type.number.or(type.bigint).optional(),
+ FrameNumber: type.number.or(type.bigint).default(0),
+ BlockAdditionID: type.number.or(type.bigint).default(0),
+ Delay: type.number.or(type.bigint).default(0),
+ SliceDuration: type.number.or(type.bigint).default(0),
});
export type TimeSliceType = typeof TimeSliceSchema.infer;
@@ -101,8 +101,8 @@ export const SlicesSchema = type({
export type SlicesType = typeof SlicesSchema.infer;
export const ReferenceFrameSchema = type({
- ReferenceOffset: type.number,
- ReferenceTimestamp: type.number,
+ ReferenceOffset: type.number.or(type.bigint),
+ ReferenceTimestamp: type.number.or(type.bigint),
});
export type ReferenceFrameType = typeof ReferenceFrameSchema.infer;
@@ -111,12 +111,12 @@ export const BlockGroupSchema = type({
Block: BlockSchema,
BlockVirtual: BinarySchema.optional(),
BlockAdditions: BlockAdditionsSchema.optional(),
- BlockDuration: type.number.optional(),
- ReferencePriority: type.number.default(0),
- ReferenceBlock: type.number.array().optional(),
- ReferenceVirtual: type.number.optional(),
+ BlockDuration: type.number.or(type.bigint).optional(),
+ ReferencePriority: type.number.or(type.bigint).default(0),
+ ReferenceBlock: type.number.or(type.bigint).array().optional(),
+ ReferenceVirtual: type.number.or(type.bigint).optional(),
CodecState: BinarySchema.optional(),
- DiscardPadding: type.number.optional(),
+ DiscardPadding: type.number.or(type.bigint).optional(),
Slices: SlicesSchema.optional(),
ReferenceFrame: ReferenceFrameSchema.optional(),
});
@@ -124,10 +124,10 @@ export const BlockGroupSchema = type({
export type BlockGroupType = typeof BlockGroupSchema.infer;
export const ClusterSchema = type({
- Timestamp: type.number,
+ Timestamp: type.number.or(type.bigint),
SilentTracks: SilentTracksSchema.optional(),
- Position: type.number.optional(),
- PrevSize: type.number.optional(),
+ Position: type.number.or(type.bigint).optional(),
+ PrevSize: type.number.or(type.bigint).optional(),
SimpleBlock: SimpleBlockSchema.array().optional(),
BlockGroup: BlockGroupSchema.array().optional(),
EncryptedBlock: BinarySchema.array().optional(),
@@ -136,9 +136,9 @@ export const ClusterSchema = type({
export type ClusterType = typeof ClusterSchema.infer;
export const BlockAdditionMappingSchema = type({
- BlockAddIDValue: type.number.optional(),
+ BlockAddIDValue: type.number.or(type.bigint).optional(),
BlockAddIDName: type.string.optional(),
- BlockAddIDType: type.number.default(0),
+ BlockAddIDType: type.number.or(type.bigint).default(0),
BlockAddIDExtraData: BinarySchema.optional(),
});
@@ -146,8 +146,8 @@ export type BlockAdditionMappingType = typeof BlockAdditionMappingSchema.infer;
export const TrackTranslateSchema = type({
TrackTranslateTrackID: BinarySchema,
- TrackTranslateCodec: type.number,
- TrackTranslateEditionUID: type.number.array().optional(),
+ TrackTranslateCodec: type.number.or(type.bigint),
+ TrackTranslateEditionUID: type.number.or(type.bigint).array().optional(),
});
export type TrackTranslateType = typeof TrackTranslateSchema.infer;
@@ -198,9 +198,12 @@ export enum MatrixCoefficientsRestrictionEnum {
CHROMA_DERIVED_CONSTANT_LUMINANCE = 13,
// ITU-R BT.2100-0
ITU_R_BT_2100_0 = 14,
-};
-export const MatrixCoefficientsRestriction = type('0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14');
-export type MatrixCoefficientsRestrictionType = typeof MatrixCoefficientsRestriction.infer;
+}
+export const MatrixCoefficientsRestriction = type(
+ '0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14'
+);
+export type MatrixCoefficientsRestrictionType =
+ typeof MatrixCoefficientsRestriction.infer;
export enum ChromaSitingHorzRestrictionEnum {
// unspecified
@@ -209,9 +212,10 @@ export enum ChromaSitingHorzRestrictionEnum {
LEFT_COLLOCATED = 1,
// half
HALF = 2,
-};
+}
export const ChromaSitingHorzRestriction = type('0 | 1 | 2');
-export type ChromaSitingHorzRestrictionType = typeof ChromaSitingHorzRestriction.infer;
+export type ChromaSitingHorzRestrictionType =
+ typeof ChromaSitingHorzRestriction.infer;
export enum ChromaSitingVertRestrictionEnum {
// unspecified
@@ -220,9 +224,10 @@ export enum ChromaSitingVertRestrictionEnum {
TOP_COLLOCATED = 1,
// half
HALF = 2,
-};
+}
export const ChromaSitingVertRestriction = type('0 | 1 | 2');
-export type ChromaSitingVertRestrictionType = typeof ChromaSitingVertRestriction.infer;
+export type ChromaSitingVertRestrictionType =
+ typeof ChromaSitingVertRestriction.infer;
export enum RangeRestrictionEnum {
// unspecified
@@ -233,7 +238,7 @@ export enum RangeRestrictionEnum {
FULL_RANGE_NO_CLIPPING = 2,
// defined by MatrixCoefficients / TransferCharacteristics
DEFINED_BY_MATRIX_COEFFICIENTS_TRANSFER_CHARACTERISTICS = 3,
-};
+}
export const RangeRestriction = type('0 | 1 | 2 | 3');
export type RangeRestrictionType = typeof RangeRestriction.infer;
@@ -276,9 +281,12 @@ export enum TransferCharacteristicsRestrictionEnum {
SMPTE_ST_428_1 = 17,
// ARIB STD-B67 (HLG)
ARIB_STD_B67_HLG = 18,
-};
-export const TransferCharacteristicsRestriction = type('0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18');
-export type TransferCharacteristicsRestrictionType = typeof TransferCharacteristicsRestriction.infer;
+}
+export const TransferCharacteristicsRestriction = type(
+ '0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18'
+);
+export type TransferCharacteristicsRestrictionType =
+ typeof TransferCharacteristicsRestriction.infer;
export enum PrimariesRestrictionEnum {
// reserved
@@ -309,24 +317,26 @@ export enum PrimariesRestrictionEnum {
SMPTE_EG_432_2 = 12,
// EBU Tech. 3213-E - JEDEC P22 phosphors
EBU_TECH_3213_E_JEDEC_P22_PHOSPHORS = 22,
-};
-export const PrimariesRestriction = type('0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 22');
+}
+export const PrimariesRestriction = type(
+ '0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 22'
+);
export type PrimariesRestrictionType = typeof PrimariesRestriction.infer;
export const ColourSchema = type({
MatrixCoefficients: MatrixCoefficientsRestriction.default(2),
- BitsPerChannel: type.number.default(0),
- ChromaSubsamplingHorz: type.number.optional(),
- ChromaSubsamplingVert: type.number.optional(),
- CbSubsamplingHorz: type.number.optional(),
- CbSubsamplingVert: type.number.optional(),
+ BitsPerChannel: type.number.or(type.bigint).default(0),
+ ChromaSubsamplingHorz: type.number.or(type.bigint).optional(),
+ ChromaSubsamplingVert: type.number.or(type.bigint).optional(),
+ CbSubsamplingHorz: type.number.or(type.bigint).optional(),
+ CbSubsamplingVert: type.number.or(type.bigint).optional(),
ChromaSitingHorz: ChromaSitingHorzRestriction.default(0),
ChromaSitingVert: ChromaSitingVertRestriction.default(0),
Range: RangeRestriction.default(0),
TransferCharacteristics: TransferCharacteristicsRestriction.default(2),
Primaries: PrimariesRestriction.default(2),
- MaxCLL: type.number.optional(),
- MaxFALL: type.number.optional(),
+ MaxCLL: type.number.or(type.bigint).optional(),
+ MaxFALL: type.number.or(type.bigint).optional(),
MasteringMetadata: MasteringMetadataSchema.optional(),
});
@@ -341,9 +351,10 @@ export enum ProjectionTypeRestrictionEnum {
CUBEMAP = 2,
// mesh
MESH = 3,
-};
+}
export const ProjectionTypeRestriction = type('0 | 1 | 2 | 3');
-export type ProjectionTypeRestrictionType = typeof ProjectionTypeRestriction.infer;
+export type ProjectionTypeRestrictionType =
+ typeof ProjectionTypeRestriction.infer;
export const ProjectionSchema = type({
ProjectionType: ProjectionTypeRestriction.default(0),
@@ -362,9 +373,10 @@ export enum FlagInterlacedRestrictionEnum {
INTERLACED = 1,
// progressive
PROGRESSIVE = 2,
-};
+}
export const FlagInterlacedRestriction = type('0 | 1 | 2');
-export type FlagInterlacedRestrictionType = typeof FlagInterlacedRestriction.infer;
+export type FlagInterlacedRestrictionType =
+ typeof FlagInterlacedRestriction.infer;
export enum FieldOrderRestrictionEnum {
// progressive
@@ -379,7 +391,7 @@ export enum FieldOrderRestrictionEnum {
TFF_INTERLEAVED = 9,
// bff (interleaved)
BFF_INTERLEAVED = 14,
-};
+}
export const FieldOrderRestriction = type('0 | 1 | 2 | 6 | 9 | 14');
export type FieldOrderRestrictionType = typeof FieldOrderRestriction.infer;
@@ -414,8 +426,10 @@ export enum StereoModeRestrictionEnum {
BOTH_EYES_LACED_IN_ONE_BLOCK_LEFT_EYE_IS_FIRST = 13,
// both eyes laced in one Block (right eye is first)
BOTH_EYES_LACED_IN_ONE_BLOCK_RIGHT_EYE_IS_FIRST = 14,
-};
-export const StereoModeRestriction = type('0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14');
+}
+export const StereoModeRestriction = type(
+ '0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14'
+);
export type StereoModeRestrictionType = typeof StereoModeRestriction.infer;
export enum AlphaModeRestrictionEnum {
@@ -423,7 +437,7 @@ export enum AlphaModeRestrictionEnum {
NONE = 0,
// present
PRESENT = 1,
-};
+}
export const AlphaModeRestriction = type('0 | 1');
export type AlphaModeRestrictionType = typeof AlphaModeRestriction.infer;
@@ -436,9 +450,10 @@ export enum OldStereoModeRestrictionEnum {
LEFT_EYE = 2,
// both eyes
BOTH_EYES = 3,
-};
+}
export const OldStereoModeRestriction = type('0 | 1 | 2 | 3');
-export type OldStereoModeRestrictionType = typeof OldStereoModeRestriction.infer;
+export type OldStereoModeRestrictionType =
+ typeof OldStereoModeRestriction.infer;
export enum DisplayUnitRestrictionEnum {
// pixels
@@ -451,7 +466,7 @@ export enum DisplayUnitRestrictionEnum {
DISPLAY_ASPECT_RATIO = 3,
// unknown
UNKNOWN = 4,
-};
+}
export const DisplayUnitRestriction = type('0 | 1 | 2 | 3 | 4');
export type DisplayUnitRestrictionType = typeof DisplayUnitRestriction.infer;
@@ -462,9 +477,10 @@ export enum AspectRatioTypeRestrictionEnum {
KEEP_ASPECT_RATIO = 1,
// fixed
FIXED = 2,
-};
+}
export const AspectRatioTypeRestriction = type('0 | 1 | 2');
-export type AspectRatioTypeRestrictionType = typeof AspectRatioTypeRestriction.infer;
+export type AspectRatioTypeRestrictionType =
+ typeof AspectRatioTypeRestriction.infer;
export const VideoSchema = type({
FlagInterlaced: FlagInterlacedRestriction.default(0),
@@ -472,14 +488,14 @@ export const VideoSchema = type({
StereoMode: StereoModeRestriction.default(0),
AlphaMode: AlphaModeRestriction.default(0),
OldStereoMode: OldStereoModeRestriction.optional(),
- PixelWidth: type.number,
- PixelHeight: type.number,
- PixelCropBottom: type.number.default(0),
- PixelCropTop: type.number.default(0),
- PixelCropLeft: type.number.default(0),
- PixelCropRight: type.number.default(0),
- DisplayWidth: type.number.optional(),
- DisplayHeight: type.number.optional(),
+ PixelWidth: type.number.or(type.bigint),
+ PixelHeight: type.number.or(type.bigint),
+ PixelCropBottom: type.number.or(type.bigint).default(0),
+ PixelCropTop: type.number.or(type.bigint).default(0),
+ PixelCropLeft: type.number.or(type.bigint).default(0),
+ PixelCropRight: type.number.or(type.bigint).default(0),
+ DisplayWidth: type.number.or(type.bigint).optional(),
+ DisplayHeight: type.number.or(type.bigint).optional(),
DisplayUnit: DisplayUnitRestriction.default(0),
AspectRatioType: AspectRatioTypeRestriction.default(0),
UncompressedFourCC: BinarySchema.optional(),
@@ -518,16 +534,18 @@ export enum EmphasisRestrictionEnum {
PHONO_LONDON = 15,
// Phono NARTB
PHONO_NARTB = 16,
-};
-export const EmphasisRestriction = type('0 | 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16');
+}
+export const EmphasisRestriction = type(
+ '0 | 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16'
+);
export type EmphasisRestrictionType = typeof EmphasisRestriction.infer;
export const AudioSchema = type({
SamplingFrequency: type.number.default(0),
OutputSamplingFrequency: type.number.optional(),
- Channels: type.number.default(1),
+ Channels: type.number.or(type.bigint).default(1),
ChannelPositions: BinarySchema.optional(),
- BitDepth: type.number.optional(),
+ BitDepth: type.number.or(type.bigint).optional(),
Emphasis: EmphasisRestriction.default(0),
});
@@ -540,12 +558,13 @@ export enum TrackPlaneTypeRestrictionEnum {
RIGHT_EYE = 1,
// background
BACKGROUND = 2,
-};
+}
export const TrackPlaneTypeRestriction = type('0 | 1 | 2');
-export type TrackPlaneTypeRestrictionType = typeof TrackPlaneTypeRestriction.infer;
+export type TrackPlaneTypeRestrictionType =
+ typeof TrackPlaneTypeRestriction.infer;
export const TrackPlaneSchema = type({
- TrackPlaneUID: type.number,
+ TrackPlaneUID: type.number.or(type.bigint),
TrackPlaneType: TrackPlaneTypeRestriction,
});
@@ -558,7 +577,7 @@ export const TrackCombinePlanesSchema = type({
export type TrackCombinePlanesType = typeof TrackCombinePlanesSchema.infer;
export const TrackJoinBlocksSchema = type({
- TrackJoinUID: type.number.array().atLeastLength(1),
+ TrackJoinUID: type.number.or(type.bigint).array().atLeastLength(1),
});
export type TrackJoinBlocksType = typeof TrackJoinBlocksSchema.infer;
@@ -579,9 +598,10 @@ export enum ContentCompAlgoRestrictionEnum {
LZO1X = 2,
// Header Stripping
HEADER_STRIPPING = 3,
-};
+}
export const ContentCompAlgoRestriction = type('0 | 1 | 2 | 3');
-export type ContentCompAlgoRestrictionType = typeof ContentCompAlgoRestriction.infer;
+export type ContentCompAlgoRestrictionType =
+ typeof ContentCompAlgoRestriction.infer;
export const ContentCompressionSchema = type({
ContentCompAlgo: ContentCompAlgoRestriction.default(0),
@@ -595,15 +615,17 @@ export enum AESSettingsCipherModeRestrictionEnum {
AES_CTR = 1,
// AES-CBC
AES_CBC = 2,
-};
+}
export const AESSettingsCipherModeRestriction = type('1 | 2');
-export type AESSettingsCipherModeRestrictionType = typeof AESSettingsCipherModeRestriction.infer;
+export type AESSettingsCipherModeRestrictionType =
+ typeof AESSettingsCipherModeRestriction.infer;
export const ContentEncAESSettingsSchema = type({
AESSettingsCipherMode: AESSettingsCipherModeRestriction,
});
-export type ContentEncAESSettingsType = typeof ContentEncAESSettingsSchema.infer;
+export type ContentEncAESSettingsType =
+ typeof ContentEncAESSettingsSchema.infer;
export enum ContentEncAlgoRestrictionEnum {
// Not encrypted
@@ -618,18 +640,20 @@ export enum ContentEncAlgoRestrictionEnum {
BLOWFISH = 4,
// AES
AES = 5,
-};
+}
export const ContentEncAlgoRestriction = type('0 | 1 | 2 | 3 | 4 | 5');
-export type ContentEncAlgoRestrictionType = typeof ContentEncAlgoRestriction.infer;
+export type ContentEncAlgoRestrictionType =
+ typeof ContentEncAlgoRestriction.infer;
export enum ContentSigAlgoRestrictionEnum {
// Not signed
NOT_SIGNED = 0,
// RSA
RSA = 1,
-};
+}
export const ContentSigAlgoRestriction = type('0 | 1');
-export type ContentSigAlgoRestrictionType = typeof ContentSigAlgoRestriction.infer;
+export type ContentSigAlgoRestrictionType =
+ typeof ContentSigAlgoRestriction.infer;
export enum ContentSigHashAlgoRestrictionEnum {
// Not signed
@@ -638,9 +662,10 @@ export enum ContentSigHashAlgoRestrictionEnum {
SHA1_160 = 1,
// MD5
MD5 = 2,
-};
+}
export const ContentSigHashAlgoRestriction = type('0 | 1 | 2');
-export type ContentSigHashAlgoRestrictionType = typeof ContentSigHashAlgoRestriction.infer;
+export type ContentSigHashAlgoRestrictionType =
+ typeof ContentSigHashAlgoRestriction.infer;
export const ContentEncryptionSchema = type({
ContentEncAlgo: ContentEncAlgoRestriction.default(0),
@@ -661,21 +686,23 @@ export enum ContentEncodingScopeRestrictionEnum {
PRIVATE = 2,
// Next
NEXT = 4,
-};
+}
export const ContentEncodingScopeRestriction = type('1 | 2 | 4');
-export type ContentEncodingScopeRestrictionType = typeof ContentEncodingScopeRestriction.infer;
+export type ContentEncodingScopeRestrictionType =
+ typeof ContentEncodingScopeRestriction.infer;
export enum ContentEncodingTypeRestrictionEnum {
// Compression
COMPRESSION = 0,
// Encryption
ENCRYPTION = 1,
-};
+}
export const ContentEncodingTypeRestriction = type('0 | 1');
-export type ContentEncodingTypeRestrictionType = typeof ContentEncodingTypeRestriction.infer;
+export type ContentEncodingTypeRestrictionType =
+ typeof ContentEncodingTypeRestriction.infer;
export const ContentEncodingSchema = type({
- ContentEncodingOrder: type.number.default(0),
+ ContentEncodingOrder: type.number.or(type.bigint).default(0),
ContentEncodingScope: ContentEncodingScopeRestriction.default(1),
ContentEncodingType: ContentEncodingTypeRestriction.default(0),
ContentCompression: ContentCompressionSchema.optional(),
@@ -707,53 +734,53 @@ export enum TrackTypeRestrictionEnum {
CONTROL = 32,
// metadata
METADATA = 33,
-};
+}
export const TrackTypeRestriction = type('1 | 2 | 3 | 16 | 17 | 18 | 32 | 33');
export type TrackTypeRestrictionType = typeof TrackTypeRestriction.infer;
export const TrackEntrySchema = type({
- TrackNumber: type.number,
- TrackUID: type.number,
+ TrackNumber: type.number.or(type.bigint),
+ TrackUID: type.number.or(type.bigint),
TrackType: TrackTypeRestriction,
- FlagEnabled: type.number.default(1),
- FlagDefault: type.number.default(1),
- FlagForced: type.number.default(0),
- FlagHearingImpaired: type.number.optional(),
- FlagVisualImpaired: type.number.optional(),
- FlagTextDescriptions: type.number.optional(),
- FlagOriginal: type.number.optional(),
- FlagCommentary: type.number.optional(),
- FlagLacing: type.number.default(1),
- MinCache: type.number.default(0),
- MaxCache: type.number.optional(),
- DefaultDuration: type.number.optional(),
- DefaultDecodedFieldDuration: type.number.optional(),
+ FlagEnabled: type.number.or(type.bigint).default(1),
+ FlagDefault: type.number.or(type.bigint).default(1),
+ FlagForced: type.number.or(type.bigint).default(0),
+ FlagHearingImpaired: type.number.or(type.bigint).optional(),
+ FlagVisualImpaired: type.number.or(type.bigint).optional(),
+ FlagTextDescriptions: type.number.or(type.bigint).optional(),
+ FlagOriginal: type.number.or(type.bigint).optional(),
+ FlagCommentary: type.number.or(type.bigint).optional(),
+ FlagLacing: type.number.or(type.bigint).default(1),
+ MinCache: type.number.or(type.bigint).default(0),
+ MaxCache: type.number.or(type.bigint).optional(),
+ DefaultDuration: type.number.or(type.bigint).optional(),
+ DefaultDecodedFieldDuration: type.number.or(type.bigint).optional(),
TrackTimestampScale: type.number.default(0),
- TrackOffset: type.number.default(0),
- MaxBlockAdditionID: type.number.default(0),
+ TrackOffset: type.number.or(type.bigint).default(0),
+ MaxBlockAdditionID: type.number.or(type.bigint).default(0),
BlockAdditionMapping: BlockAdditionMappingSchema.array().optional(),
Name: type.string.optional(),
- Language: type.string.default("eng"),
+ Language: type.string.default('eng'),
LanguageBCP47: type.string.optional(),
CodecID: type.string,
CodecPrivate: BinarySchema.optional(),
CodecName: type.string.optional(),
- AttachmentLink: type.number.optional(),
+ AttachmentLink: type.number.or(type.bigint).optional(),
CodecSettings: type.string.optional(),
CodecInfoURL: type.string.array().optional(),
CodecDownloadURL: type.string.array().optional(),
- CodecDecodeAll: type.number.default(1),
- TrackOverlay: type.number.array().optional(),
- CodecDelay: type.number.default(0),
- SeekPreRoll: type.number.default(0),
+ CodecDecodeAll: type.number.or(type.bigint).default(1),
+ TrackOverlay: type.number.or(type.bigint).array().optional(),
+ CodecDelay: type.number.or(type.bigint).default(0),
+ SeekPreRoll: type.number.or(type.bigint).default(0),
TrackTranslate: TrackTranslateSchema.array().optional(),
Video: VideoSchema.optional(),
Audio: AudioSchema.optional(),
TrackOperation: TrackOperationSchema.optional(),
- TrickTrackUID: type.number.optional(),
+ TrickTrackUID: type.number.or(type.bigint).optional(),
TrickTrackSegmentUID: BinarySchema.optional(),
- TrickTrackFlag: type.number.default(0),
- TrickMasterTrackUID: type.number.optional(),
+ TrickTrackFlag: type.number.or(type.bigint).default(0),
+ TrickMasterTrackUID: type.number.or(type.bigint).optional(),
TrickMasterTrackSegmentUID: BinarySchema.optional(),
ContentEncodings: ContentEncodingsSchema.optional(),
});
@@ -767,28 +794,28 @@ export const TracksSchema = type({
export type TracksType = typeof TracksSchema.infer;
export const CueReferenceSchema = type({
- CueRefTime: type.number,
- CueRefCluster: type.number,
- CueRefNumber: type.number.default(1),
- CueRefCodecState: type.number.default(0),
+ CueRefTime: type.number.or(type.bigint),
+ CueRefCluster: type.number.or(type.bigint),
+ CueRefNumber: type.number.or(type.bigint).default(1),
+ CueRefCodecState: type.number.or(type.bigint).default(0),
});
export type CueReferenceType = typeof CueReferenceSchema.infer;
export const CueTrackPositionsSchema = type({
- CueTrack: type.number,
- CueClusterPosition: type.number,
- CueRelativePosition: type.number.optional(),
- CueDuration: type.number.optional(),
- CueBlockNumber: type.number.optional(),
- CueCodecState: type.number.default(0),
+ CueTrack: type.number.or(type.bigint),
+ CueClusterPosition: type.number.or(type.bigint),
+ CueRelativePosition: type.number.or(type.bigint).optional(),
+ CueDuration: type.number.or(type.bigint).optional(),
+ CueBlockNumber: type.number.or(type.bigint).optional(),
+ CueCodecState: type.number.or(type.bigint).default(0),
CueReference: CueReferenceSchema.array().optional(),
});
export type CueTrackPositionsType = typeof CueTrackPositionsSchema.infer;
export const CuePointSchema = type({
- CueTime: type.number,
+ CueTime: type.number.or(type.bigint),
CueTrackPositions: CueTrackPositionsSchema.array().atLeastLength(1),
});
@@ -805,10 +832,10 @@ export const AttachedFileSchema = type({
FileName: type.string,
FileMediaType: type.string,
FileData: BinarySchema,
- FileUID: type.number,
+ FileUID: type.number.or(type.bigint),
FileReferral: BinarySchema.optional(),
- FileUsedStartTime: type.number.optional(),
- FileUsedEndTime: type.number.optional(),
+ FileUsedStartTime: type.number.or(type.bigint).optional(),
+ FileUsedEndTime: type.number.or(type.bigint).optional(),
});
export type AttachedFileType = typeof AttachedFileSchema.infer;
@@ -826,13 +853,110 @@ export const EditionDisplaySchema = type({
export type EditionDisplayType = typeof EditionDisplaySchema.infer;
-export const EditionEntrySchema = type({
- EditionUID: type.number.optional(),
- EditionFlagHidden: type.number.default(0),
- EditionFlagDefault: type.number.default(0),
- EditionFlagOrdered: type.number.default(0),
- EditionDisplay: EditionDisplaySchema.array().optional(),
+export const ChapterTrackSchema = type({
+ ChapterTrackUID: type.number.or(type.bigint).array().atLeastLength(1),
+});
+export type ChapterTrackType = typeof ChapterTrackSchema.infer;
+
+export const ChapLanguageSchema = match({
+ 'string[]': (v) => (v.length > 0 ? v : ['eng']),
+ default: () => ['eng'],
+}).optional();
+
+export const ChapterDisplaySchema = type({
+ ChapString: type.string,
+ ChapLanguage: ChapLanguageSchema,
+ ChapLanguageBCP47: type.string.array().optional(),
+ ChapCountry: type.string.array().optional(),
+});
+
+export type ChapterDisplayType = typeof ChapterDisplaySchema.infer;
+
+export enum ChapProcessTimeRestrictionEnum {
+ // during the whole chapter
+ DURING_THE_WHOLE_CHAPTER = 0,
+ // before starting playback
+ BEFORE_STARTING_PLAYBACK = 1,
+ // after playback of the chapter
+ AFTER_PLAYBACK_OF_THE_CHAPTER = 2,
+}
+export const ChapProcessTimeRestriction = type('0 | 1 | 2');
+export type ChapProcessTimeRestrictionType =
+ typeof ChapProcessTimeRestriction.infer;
+
+export const ChapProcessCommandSchema = type({
+ ChapProcessTime: ChapProcessTimeRestriction,
+ ChapProcessData: BinarySchema,
+});
+
+export type ChapProcessCommandType = typeof ChapProcessCommandSchema.infer;
+
+export enum ChapProcessCodecIDRestrictionEnum {
+ // Matroska Script
+ MATROSKA_SCRIPT = 0,
+ // DVD-menu
+ DVD_MENU = 1,
+}
+export const ChapProcessCodecIDRestriction = type('0 | 1');
+export type ChapProcessCodecIDRestrictionType =
+ typeof ChapProcessCodecIDRestriction.infer;
+
+export const ChapProcessSchema = type({
+ ChapProcessCodecID: ChapProcessCodecIDRestriction.default(0),
+ ChapProcessPrivate: BinarySchema.optional(),
+ ChapProcessCommand: ChapProcessCommandSchema.array().optional(),
+});
+
+export type ChapProcessType = typeof ChapProcessSchema.infer;
+
+export enum ChapterSkipTypeRestrictionEnum {
+ // No Skipping
+ NO_SKIPPING = 0,
+ // Opening Credits
+ OPENING_CREDITS = 1,
+ // End Credits
+ END_CREDITS = 2,
+ // Recap
+ RECAP = 3,
+ // Next Preview
+ NEXT_PREVIEW = 4,
+ // Preview
+ PREVIEW = 5,
+ // Advertisement
+ ADVERTISEMENT = 6,
+ // Intermission
+ INTERMISSION = 7,
+}
+export const ChapterSkipTypeRestriction = type('0 | 1 | 2 | 3 | 4 | 5 | 6 | 7');
+export type ChapterSkipTypeRestrictionType =
+ typeof ChapterSkipTypeRestriction.infer;
+
+export const ChapterAtomSchema = type({
+ ChapterUID: type.number.or(type.bigint),
+ ChapterStringUID: type.string.optional(),
+ ChapterTimeStart: type.number.or(type.bigint),
+ ChapterTimeEnd: type.number.or(type.bigint).optional(),
+ ChapterFlagHidden: type.number.or(type.bigint).default(0),
+ ChapterFlagEnabled: type.number.or(type.bigint).default(1),
+ ChapterSegmentUUID: BinarySchema.optional(),
+ ChapterSkipType: ChapterSkipTypeRestriction.optional(),
+ ChapterSegmentEditionUID: type.number.or(type.bigint).optional(),
+ ChapterPhysicalEquiv: type.number.or(type.bigint).optional(),
+ ChapterTrack: ChapterTrackSchema.optional(),
+ ChapterDisplay: ChapterDisplaySchema.array().optional(),
+ ChapProcess: ChapProcessSchema.array().optional(),
+});
+
+export type ChapterAtomType = typeof ChapterAtomSchema.infer;
+
+export const EditionEntrySchema = type({
+ EditionUID: type.number.or(type.bigint).optional(),
+ EditionFlagHidden: type.number.or(type.bigint).default(0),
+ EditionFlagDefault: type.number.or(type.bigint).default(0),
+ EditionFlagOrdered: type.number.or(type.bigint).default(0),
+ EditionDisplay: EditionDisplaySchema.array().optional(),
+ ChapterAtom: ChapterAtomSchema.array().atLeastLength(1),
});
export type EditionEntryType = typeof EditionEntrySchema.infer;
@@ -844,28 +968,24 @@ export const ChaptersSchema = type({
export type ChaptersType = typeof ChaptersSchema.infer;
export const TagTrackUIDSchema = match({
- "number[]": v => v.length > 0 ? v : [0],
- "undefined": () => [0],
- default: "assert"
-});
+ '(number | bigint)[]': (v) => (v.length > 0 ? v : [0]),
+ default: () => [0],
+}).optional();
export const TagEditionUIDSchema = match({
- "number[]": v => v.length > 0 ? v : [0],
- "undefined": () => [0],
- default: "assert"
-});
+ '(number | bigint)[]': (v) => (v.length > 0 ? v : [0]),
+ default: () => [0],
+}).optional();
export const TagChapterUIDSchema = match({
- "number[]": v => v.length > 0 ? v : [0],
- "undefined": () => [0],
- default: "assert"
-});
+ '(number | bigint)[]': (v) => (v.length > 0 ? v : [0]),
+ default: () => [0],
+}).optional();
export const TagAttachmentUIDSchema = match({
- "number[]": v => v.length > 0 ? v : [0],
- "undefined": () => [0],
- default: "assert"
-});
+ '(number | bigint)[]': (v) => (v.length > 0 ? v : [0]),
+ default: () => [0],
+}).optional();
export enum TargetTypeValueRestrictionEnum {
// SHOT
@@ -882,55 +1002,60 @@ export enum TargetTypeValueRestrictionEnum {
EDITION_ISSUE_VOLUME_OPUS_SEASON_SEQUEL = 60,
// COLLECTION
COLLECTION = 70,
-};
-export const TargetTypeValueRestriction = type('10 | 20 | 30 | 40 | 50 | 60 | 70');
-export type TargetTypeValueRestrictionType = typeof TargetTypeValueRestriction.infer;
+}
+export const TargetTypeValueRestriction = type(
+ '10 | 20 | 30 | 40 | 50 | 60 | 70'
+);
+export type TargetTypeValueRestrictionType =
+ typeof TargetTypeValueRestriction.infer;
export enum TargetTypeRestrictionEnum {
// TargetTypeValue 70
- COLLECTION = "COLLECTION",
+ COLLECTION = 'COLLECTION',
// TargetTypeValue 60
- EDITION = "EDITION",
+ EDITION = 'EDITION',
// TargetTypeValue 60
- ISSUE = "ISSUE",
+ ISSUE = 'ISSUE',
// TargetTypeValue 60
- VOLUME = "VOLUME",
+ VOLUME = 'VOLUME',
// TargetTypeValue 60
- OPUS = "OPUS",
+ OPUS = 'OPUS',
// TargetTypeValue 60
- SEASON = "SEASON",
+ SEASON = 'SEASON',
// TargetTypeValue 60
- SEQUEL = "SEQUEL",
+ SEQUEL = 'SEQUEL',
// TargetTypeValue 50
- ALBUM = "ALBUM",
+ ALBUM = 'ALBUM',
// TargetTypeValue 50
- OPERA = "OPERA",
+ OPERA = 'OPERA',
// TargetTypeValue 50
- CONCERT = "CONCERT",
+ CONCERT = 'CONCERT',
// TargetTypeValue 50
- MOVIE = "MOVIE",
+ MOVIE = 'MOVIE',
// TargetTypeValue 50
- EPISODE = "EPISODE",
+ EPISODE = 'EPISODE',
// TargetTypeValue 40
- PART = "PART",
+ PART = 'PART',
// TargetTypeValue 40
- SESSION = "SESSION",
+ SESSION = 'SESSION',
// TargetTypeValue 30
- TRACK = "TRACK",
+ TRACK = 'TRACK',
// TargetTypeValue 30
- SONG = "SONG",
+ SONG = 'SONG',
// TargetTypeValue 30
- CHAPTER = "CHAPTER",
+ CHAPTER = 'CHAPTER',
// TargetTypeValue 20
- SUBTRACK = "SUBTRACK",
+ SUBTRACK = 'SUBTRACK',
// TargetTypeValue 20
- MOVEMENT = "MOVEMENT",
+ MOVEMENT = 'MOVEMENT',
// TargetTypeValue 20
- SCENE = "SCENE",
+ SCENE = 'SCENE',
// TargetTypeValue 10
- SHOT = "SHOT",
-};
-export const TargetTypeRestriction = type('"COLLECTION" | "EDITION" | "ISSUE" | "VOLUME" | "OPUS" | "SEASON" | "SEQUEL" | "ALBUM" | "OPERA" | "CONCERT" | "MOVIE" | "EPISODE" | "PART" | "SESSION" | "TRACK" | "SONG" | "CHAPTER" | "SUBTRACK" | "MOVEMENT" | "SCENE" | "SHOT"');
+ SHOT = 'SHOT',
+}
+export const TargetTypeRestriction = type(
+ '"COLLECTION" | "EDITION" | "ISSUE" | "VOLUME" | "OPUS" | "SEASON" | "SEQUEL" | "ALBUM" | "OPERA" | "CONCERT" | "MOVIE" | "EPISODE" | "PART" | "SESSION" | "TRACK" | "SONG" | "CHAPTER" | "SUBTRACK" | "MOVEMENT" | "SCENE" | "SHOT"'
+);
export type TargetTypeRestrictionType = typeof TargetTypeRestriction.infer;
export const TargetsSchema = type({
@@ -944,9 +1069,21 @@ export const TargetsSchema = type({
export type TargetsType = typeof TargetsSchema.infer;
+export const SimpleTagSchema = type({
+ TagName: type.string,
+ TagLanguage: type.string.default('und'),
+ TagLanguageBCP47: type.string.optional(),
+ TagDefault: type.number.or(type.bigint).default(1),
+ TagDefaultBogus: type.number.or(type.bigint).default(1),
+ TagString: type.string.optional(),
+ TagBinary: BinarySchema.optional(),
+});
+
+export type SimpleTagType = typeof SimpleTagSchema.infer;
+
export const TagSchema = type({
Targets: TargetsSchema,
-
+ SimpleTag: SimpleTagSchema.array().atLeastLength(1),
});
export type TagType = typeof TagSchema.infer;
@@ -998,14 +1135,23 @@ export const IdMultiSet = new Set([
EbmlTagIdEnum.CuePoint,
EbmlTagIdEnum.AttachedFile,
EbmlTagIdEnum.EditionLanguageIETF,
+ EbmlTagIdEnum.ChapterTrackUID,
+ EbmlTagIdEnum.ChapLanguage,
+ EbmlTagIdEnum.ChapLanguageBCP47,
+ EbmlTagIdEnum.ChapCountry,
+ EbmlTagIdEnum.ChapProcessCommand,
+ EbmlTagIdEnum.ChapterDisplay,
+ EbmlTagIdEnum.ChapProcess,
EbmlTagIdEnum.EditionDisplay,
+ EbmlTagIdEnum.ChapterAtom,
EbmlTagIdEnum.EditionEntry,
EbmlTagIdEnum.TagTrackUID,
EbmlTagIdEnum.TagEditionUID,
EbmlTagIdEnum.TagChapterUID,
EbmlTagIdEnum.TagAttachmentUID,
+ EbmlTagIdEnum.SimpleTag,
EbmlTagIdEnum.Tag,
EbmlTagIdEnum.SeekHead,
EbmlTagIdEnum.Cluster,
- EbmlTagIdEnum.Tags
-])
\ No newline at end of file
+ EbmlTagIdEnum.Tags,
+]);
diff --git a/apps/playground/src/media/mkv/util.ts b/apps/playground/src/media/mkv/util.ts
index 9d445e4..59cbca0 100644
--- a/apps/playground/src/media/mkv/util.ts
+++ b/apps/playground/src/media/mkv/util.ts
@@ -27,7 +27,7 @@ export function isTagPos<
pos === '*' || pos === tag.position;
}
-export function convertEbmlTagToComponent (tag: EbmlTagType) {
+export function convertEbmlTagToComponent(tag: EbmlTagType) {
if (tag.type === EbmlElementType.Master) {
const obj: Record = {};
const children = tag.children;
@@ -51,3 +51,12 @@ export function convertEbmlTagToComponent (tag: EbmlTagType) {
}
return tag.data;
}
+
+export function waitTick() {
+ return new Promise((resolve) => {
+ const timeout = setTimeout(() => {
+ resolve();
+ timeout && clearTimeout(timeout);
+ }, 0);
+ });
+}
diff --git a/apps/playground/src/video-pipeline-demo.ts b/apps/playground/src/video-pipeline-demo.ts
index e6e2bb5..d3b892c 100644
--- a/apps/playground/src/video-pipeline-demo.ts
+++ b/apps/playground/src/video-pipeline-demo.ts
@@ -1,49 +1,394 @@
import { html, css, LitElement } from 'lit';
import { property } from 'lit/decorators.js';
-import { type Subscription, switchMap, take } from 'rxjs';
+import {
+ animationFrames,
+ BehaviorSubject,
+ combineLatest,
+ ReplaySubject,
+ EMPTY,
+ map,
+ Observable,
+ shareReplay,
+ Subject,
+ Subscription,
+ switchMap,
+ take,
+ tap,
+ distinctUntilChanged,
+ fromEvent,
+ filter,
+} from 'rxjs';
import { createEbmlController } from './media/mkv/reactive';
+import { TrackTypeRestrictionEnum, type ClusterType } from './media/mkv/schema';
+import type { SegmentComponent } from './media/mkv/model';
+import { createRef, ref, type Ref } from 'lit/directives/ref.js';
+import { Queue } from 'mnemonist';
+import { dataViewSliceToBuf } from 'konoebml';
export class VideoPipelineDemo extends LitElement {
+ static styles = css``;
+
@property()
src!: string;
- subscripton?: Subscription;
+ @property({ type: Number })
+ width = 1280;
- static styles = css``;
+ @property({ type: Number })
+ height = 720;
- async prepareVideoPipeline() {
- if (!this.src) {
+ canvasRef: Ref = createRef();
+ audioContext = new AudioContext();
+
+ seek$ = new ReplaySubject(1);
+ cluster$ = new Subject>();
+ videoFrameBuffer$ = new BehaviorSubject(new Queue());
+ audioFrameBuffer$ = new BehaviorSubject(new Queue());
+ pipeline$$?: Subscription;
+ bridge$$?: Subscription;
+ private startTime = 0;
+
+ paused$ = new BehaviorSubject(false);
+ ended$ = new BehaviorSubject(false);
+
+ private preparePipeline() {
+ const src = this.src;
+ if (!src) {
return;
}
- const { controller$ } = createEbmlController(this.src);
-
- this.subscripton = controller$
- .pipe(
- switchMap(({ segments$ }) => segments$.pipe(take(1))),
- switchMap(({ seek }) => seek(0))
- )
- .subscribe((cluster) => console.log(cluster));
-
- const videoDecoder = new VideoDecoder({
- output: (frame) => {},
- error: (e) => {
- e;
- },
+ const { controller$ } = createEbmlController({
+ url: src,
});
+
+ const segment$ = controller$.pipe(
+ switchMap(({ segments$ }) => segments$.pipe(take(1)))
+ );
+
+ const cluster$ = combineLatest({
+ seekTime: this.seek$,
+ segment: segment$,
+ }).pipe(switchMap(({ seekTime, segment }) => segment.seek(seekTime)));
+
+ const decode$ = segment$.pipe(
+ switchMap(({ withMeta$ }) => withMeta$),
+ map((segment) => {
+ const trackSystem = segment.track;
+ const infoSystem = segment.info;
+ const tracks = {
+ video: trackSystem.getTrackEntry({
+ predicate: (c) =>
+ c.TrackType === TrackTypeRestrictionEnum.VIDEO &&
+ c.FlagEnabled !== 0,
+ }),
+ audio: trackSystem.getTrackEntry({
+ predicate: (c) =>
+ c.TrackType === TrackTypeRestrictionEnum.AUDIO &&
+ c.FlagEnabled !== 0,
+ }),
+ subtitle: trackSystem.getTrackEntry({
+ predicate: (c) =>
+ c.TrackType === TrackTypeRestrictionEnum.SUBTITLE &&
+ c.FlagEnabled !== 0,
+ }),
+ };
+
+ const videoDecode$ = tracks.video
+ ? new Observable((subscriber) => {
+ let isFinalized = false;
+ const videoTrack = tracks.video!;
+ const decoder = new VideoDecoder({
+ output: (frame) => {
+ subscriber.next(frame);
+ },
+ error: (e) => {
+ if (!isFinalized) {
+ isFinalized = true;
+ subscriber.error(e);
+ }
+ },
+ });
+
+ decoder.configure({
+ codec: 'hev1.2.2.L93.B0', // codec: 'vp8',
+ hardwareAcceleration: 'prefer-hardware',
+ description: videoTrack.CodecPrivate, // Uint8Array,包含 VPS/SPS/PPS
+ });
+
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity:
+ const sub = this.cluster$.subscribe((c) => {
+ if (!isFinalized) {
+ for (const b of (c.SimpleBlock || []).filter(
+ (b) => b.track === videoTrack.TrackNumber
+ )) {
+ const chunk = new EncodedVideoChunk({
+ type: b.keyframe ? 'key' : 'delta',
+ timestamp:
+ ((infoSystem.info.TimestampScale as number) / 1000) *
+ ((c.Timestamp as number) + b.value),
+ data: b.payload,
+ });
+ decoder.decode(chunk);
+ }
+ }
+ });
+
+ return () => {
+ if (!isFinalized) {
+ isFinalized = true;
+ decoder.close();
+ }
+ sub.unsubscribe();
+ };
+ })
+ : EMPTY;
+
+ const audioDecode$ = tracks.audio
+ ? new Observable((subscriber) => {
+ let isFinalized = false;
+
+ const decoder = new AudioDecoder({
+ output: (audioData) => {
+ subscriber.next(audioData);
+ },
+ error: (e) => {
+ if (!isFinalized) {
+ isFinalized = true;
+ subscriber.error(e);
+ }
+ },
+ });
+
+ const audioTrack = tracks.audio!;
+ const sampleRate = audioTrack.Audio?.SamplingFrequency || 44100;
+ const codec = 'mp4a.40.2';
+ const numberOfChannels =
+ (audioTrack.Audio?.Channels as number) || 2;
+ const duration =
+ Math.round(Number(audioTrack.DefaultDuration / 1000)) ||
+ Math.round((1024 / sampleRate) * 1000000);
+
+ decoder.configure({
+ codec: codec,
+ description: audioTrack.CodecPrivate,
+ numberOfChannels,
+ sampleRate,
+ });
+
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity:
+ const sub = this.cluster$.subscribe((c) => {
+ if (!isFinalized) {
+ for (const b of (c.SimpleBlock || []).filter(
+ (b) => b.track === audioTrack.TrackNumber
+ )) {
+ const blockTime = (c.Timestamp as number) + b.value;
+ let n = 0;
+ for (const f of b.frames) {
+ const offsetTimeUs = (n + 1) * duration;
+ decoder.decode(
+ new EncodedAudioChunk({
+ type: b.keyframe ? 'key' : 'delta',
+ timestamp:
+ ((infoSystem.info.TimestampScale as number) /
+ 1000) *
+ blockTime +
+ offsetTimeUs,
+ data: f,
+ })
+ );
+ n += 1;
+ }
+ }
+ }
+ });
+
+ return () => {
+ if (!isFinalized) {
+ isFinalized = true;
+ }
+ sub.unsubscribe();
+ };
+ })
+ : EMPTY;
+
+ return {
+ video$: videoDecode$,
+ audio$: audioDecode$,
+ };
+ }),
+ shareReplay(1)
+ );
+
+ const addToVideoFrameBuffer$ = decode$.pipe(
+ switchMap((decode) => decode.video$),
+ tap((frame) => {
+ const buffer = this.videoFrameBuffer$.getValue();
+ buffer.enqueue(frame);
+ this.videoFrameBuffer$.next(buffer);
+ })
+ );
+
+ const addToAudioFrameBuffer$ = decode$.pipe(
+ switchMap((decode) => decode.audio$),
+ tap((frame) => {
+ const buffer = this.audioFrameBuffer$.getValue();
+ buffer.enqueue(frame);
+ this.audioFrameBuffer$.next(buffer);
+ })
+ );
+
+ const audio$ = combineLatest({
+ paused: this.paused$,
+ ended: this.ended$,
+ buffered: this.audioFrameBuffer$.pipe(
+ map((q) => q.size >= 1),
+ distinctUntilChanged()
+ ),
+ }).pipe(
+ map(({ ended, paused, buffered }) => !paused && !ended && !!buffered),
+ switchMap((enabled) => (enabled ? animationFrames() : EMPTY)),
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity:
+ tap(() => {
+ const audioFrameBuffer = this.audioFrameBuffer$.getValue();
+ const nowTime = performance.now();
+ const accTime = nowTime - this.startTime;
+ let audioChanged = false;
+ while (audioFrameBuffer.size > 0) {
+ const firstAudio = audioFrameBuffer.peek();
+ if (firstAudio && firstAudio.timestamp <= accTime * 1000) {
+ const audioFrame = audioFrameBuffer.dequeue()!;
+ audioChanged = true;
+ const audioContext = this.audioContext;
+
+ if (audioContext) {
+ const numberOfChannels = audioFrame.numberOfChannels;
+ const sampleRate = audioFrame.sampleRate;
+ const numberOfFrames = audioFrame.numberOfFrames;
+ const data = new Float32Array(numberOfFrames * numberOfChannels);
+ audioFrame.copyTo(data, {
+ planeIndex: 0,
+ });
+
+ const audioBuffer = audioContext.createBuffer(
+ numberOfChannels,
+ numberOfFrames,
+ sampleRate
+ );
+
+ for (let channel = 0; channel < numberOfChannels; channel++) {
+ const channelData = audioBuffer.getChannelData(channel);
+ for (let i = 0; i < numberOfFrames; i++) {
+ channelData[i] = data[i * numberOfChannels + channel];
+ }
+ }
+
+ const audioTime = audioFrame.timestamp / 1000000;
+
+ audioFrame.close();
+
+ if (audioContext.state === 'running') {
+ const audioSource = audioContext.createBufferSource();
+ audioSource.buffer = audioBuffer;
+ audioSource.connect(audioContext.destination);
+
+ audioSource.start(
+ audioContext.currentTime +
+ Math.max(0, audioTime - accTime / 1000)
+ );
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ if (audioChanged) {
+ this.audioFrameBuffer$.next(this.audioFrameBuffer$.getValue());
+ }
+ })
+ );
+
+ const video$ = combineLatest({
+ paused: this.paused$,
+ ended: this.ended$,
+ buffered: this.videoFrameBuffer$.pipe(
+ map((q) => q.size >= 1),
+ distinctUntilChanged()
+ ),
+ }).pipe(
+ map(({ ended, paused, buffered }) => !paused && !ended && !!buffered),
+ switchMap((enabled) => (enabled ? animationFrames() : EMPTY)),
+ tap(() => {
+ const videoFrameBuffer = this.videoFrameBuffer$.getValue();
+ let videoChanged = false;
+ const nowTime = performance.now();
+ const accTime = nowTime - this.startTime;
+ while (videoFrameBuffer.size > 0) {
+ const firstVideo = videoFrameBuffer.peek();
+ if (firstVideo && firstVideo.timestamp <= accTime * 1000) {
+ const videoFrame = videoFrameBuffer.dequeue()!;
+ const canvas = this.canvasRef.value;
+ const canvas2dContext = canvas?.getContext('2d');
+ if (canvas2dContext) {
+ canvas2dContext.drawImage(
+ videoFrame,
+ 0,
+ 0,
+ this.width,
+ this.height
+ );
+ videoFrame.close();
+ videoChanged = true;
+ }
+ } else {
+ break;
+ }
+ }
+ if (videoChanged) {
+ this.videoFrameBuffer$.next(videoFrameBuffer);
+ }
+ })
+ );
+
+ this.pipeline$$ = new Subscription();
+ this.pipeline$$.add(audio$.subscribe());
+ this.pipeline$$.add(video$.subscribe());
+ this.pipeline$$.add(addToVideoFrameBuffer$.subscribe());
+ this.pipeline$$.add(addToAudioFrameBuffer$.subscribe());
+ this.pipeline$$.add(cluster$.subscribe(this.cluster$));
+ this.pipeline$$.add(
+ fromEvent(document.body, 'click').subscribe(() => {
+ this.audioContext.resume();
+ this.audioFrameBuffer$.next(this.audioFrameBuffer$.getValue());
+ })
+ );
}
connectedCallback(): void {
super.connectedCallback();
- this.prepareVideoPipeline();
+ this.preparePipeline();
+ this.seek(0);
}
disconnectedCallback(): void {
super.disconnectedCallback();
- this.subscripton?.unsubscribe();
+ this.pipeline$$?.unsubscribe();
+ }
+
+ seek(seekTime: number) {
+ this.seek$.next(seekTime);
+ }
+
+ play() {
+ this.paused$.next(false);
+ }
+
+ pause() {
+ this.paused$.next(true);
}
render() {
- return html``;
+ return html`
+
+ `;
}
}
diff --git a/apps/proxy/.whistle/rules/files/0.konoplayer b/apps/proxy/.whistle/rules/files/0.konoplayer
index 7564a08..6057e67 100644
--- a/apps/proxy/.whistle/rules/files/0.konoplayer
+++ b/apps/proxy/.whistle/rules/files/0.konoplayer
@@ -5,7 +5,7 @@
}
```
-# ^https://konoplayer.com/api/static/*** resSpeed://1024K
+^https://konoplayer.com/api/static/*** resSpeed://10240
^https://konoplayer.com/api*** reqHeaders://{x-forwarded.json} http://127.0.0.1:5001/api$1
^https://konoplayer.com/*** reqHeaders://{x-forwarded.json} http://127.0.0.1:5000/$1 excludeFilter://^https://konoplayer.com/api
^wss://konoplayer.com/*** reqHeaders://{x-forwarded.json} ws://127.0.0.1:5000/$1 excludeFilter://^wss://konoplayer.com/api
\ No newline at end of file
diff --git a/biome.jsonc b/biome.jsonc
index ccfbb04..e02fabf 100644
--- a/biome.jsonc
+++ b/biome.jsonc
@@ -52,7 +52,8 @@
"linter": {
"rules": {
"suspicious": {
- "noConsole": "off"
+ "noConsole": "off",
+ "noConsoleLog": "off"
},
"performance": {
"useTopLevelRegex": "off"
diff --git a/justfile b/justfile
index 19177ee..243d287 100644
--- a/justfile
+++ b/justfile
@@ -5,4 +5,7 @@ dev-playground:
pnpm run --filter=playground dev
dev-proxy:
- pnpm run --filter proxy --filter mock dev
\ No newline at end of file
+ pnpm run --filter proxy --filter mock dev
+
+download-samples:
+ pnpm run download-samples
\ No newline at end of file
diff --git a/package.json b/package.json
index 4a4c648..e159c6a 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,8 @@
"version": "0.0.1",
"description": "A strange player, like the dumtruck, taking you to Isekai.",
"scripts": {
- "codegen-mkv": "tsx --tsconfig=./tsconfig.scripts.json ./scripts/codegen-mkv.ts"
+ "codegen-mkv": "tsx --tsconfig=./tsconfig.scripts.json ./scripts/codegen-mkv.ts",
+ "download-samples": "tsx --tsconfig=./tsconfig.scripts.json ./scripts/download-samples.ts"
},
"keywords": [],
"author": "lonelyhentxi",
@@ -15,12 +16,12 @@
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
- "@types/node": "^22.13.8",
+ "@types/node": "^22.13.11",
"change-case": "^5.4.4",
"happy-dom": "^17.4.4",
- "tsx": "^4.19.2",
+ "tsx": "^4.19.3",
"typescript": "^5.8.2",
- "ultracite": "^4.1.15"
+ "ultracite": "^4.2.0"
},
"dependencies": {
"@types/lodash-es": "^4.17.12",
diff --git a/packages/codecs/Cargo.toml b/packages/codecs/Cargo.toml
new file mode 100644
index 0000000..5b0d574
--- /dev/null
+++ b/packages/codecs/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "konoplayer-codecs"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+ffmpeg-sys-next = { version = "7.1.0", features = ["avcodec"] }
diff --git a/packages/codecs/src/lib.rs b/packages/codecs/src/lib.rs
new file mode 100644
index 0000000..d7a0a72
--- /dev/null
+++ b/packages/codecs/src/lib.rs
@@ -0,0 +1,85 @@
+use ffmpeg_sys_next as ffmpeg;
+
+fn get_webcodecs_codec(codec_id: &str, codec_private: &[u8]) -> Result {
+ unsafe {
+ // 根据 CodecID 获取 AVCodec
+ let codec = match codec_id {
+ "V_VP8" => ffmpeg::AVCodecID::AV_CODEC_ID_VP8,
+ "V_VP9" => ffmpeg::AVCodecID::AV_CODEC_ID_VP9,
+ "V_MPEG4/ISO/AVC" => ffmpeg::AVCodecID::AV_CODEC_ID_H264,
+ "V_MPEGH/ISO/HEVC" => ffmpeg::AVCodecID::AV_CODEC_ID_HEVC,
+ _ => return Err(format!("Unsupported CodecID: {}", codec_id)),
+ };
+
+ let av_codec = ffmpeg::avcodec_find_decoder(codec);
+ if av_codec.is_null() {
+ return Err("Codec not found".to_string());
+ }
+
+ let context = ffmpeg::avcodec_alloc_context3(av_codec);
+ if context.is_null() {
+ return Err("Failed to allocate context".to_string());
+ }
+
+ // 设置 CodecPrivate 数据
+ (*context).extradata = codec_private.as_ptr() as *mut u8;
+ (*context).extradata_size = codec_private.len() as i32;
+
+ // 解析参数
+ match codec_id {
+ "V_VP9" => {
+ // VP9: 假设默认值,实际需解析帧数据
+ Ok("vp09.00.10.08".to_string())
+ }
+ "V_MPEG4/ISO/AVC" => {
+ let profile = (*context).profile; // FFmpeg 提供 profile
+ let level = (*context).level;
+ Ok(format!("avc1.{:02x}00{:02x}", profile, level))
+ }
+ "V_MPEGH/ISO/HEVC" => {
+ let profile = (*context).profile;
+ let level = (*context).level;
+ Ok(format!("hev1.{}.0.{}.B0", profile, level))
+ }
+ _ => unreachable!(),
+ }
+ }
+}
+
+pub fn add(left: u64, right: u64) -> u64 {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+
+ #[test]
+ fn main() {
+ let codec_id = "V_MPEGH/ISO/HEVC";
+ let codec_private = vec![
+ 1, 2, 32, 0, 0, 0, 144, 0, 0, 0, 0, 0, 120, 240, 0, 252, 253, 250, 250, 0, 0, 15, 4,
+ 160, 0, 1, 0, 25, 64, 1, 12, 1, 255, 255, 2, 32, 0, 0, 3, 0, 144, 0, 0, 3, 0, 0, 3, 0,
+ 120, 153, 138, 2, 64, 161, 0, 1, 0, 44, 66, 1, 1, 2, 32, 0, 0, 3, 0, 144, 0, 0, 3, 0,
+ 0, 3, 0, 120, 160, 3, 192, 128, 16, 228, 217, 102, 98, 174, 70, 194, 166, 160, 32, 32,
+ 60, 32, 0, 0, 125, 32, 0, 11, 184, 1, 162, 0, 1, 0, 9, 68, 1, 193, 114, 138, 86, 113,
+ 178, 64, 167, 0, 1, 0, 121, 78, 1, 5, 116, 44, 162, 222, 9, 181, 23, 71, 219, 187, 85,
+ 164, 254, 127, 194, 252, 78, 120, 50, 54, 53, 32, 45, 32, 45, 32, 72, 46, 50, 54, 53,
+ 47, 72, 69, 86, 67, 32, 99, 111, 100, 101, 99, 32, 45, 32, 67, 111, 112, 121, 114, 105,
+ 103, 104, 116, 32, 50, 48, 49, 51, 45, 50, 48, 49, 56, 32, 40, 99, 41, 32, 77, 117,
+ 108, 116, 105, 99, 111, 114, 101, 119, 97, 114, 101, 44, 32, 73, 110, 99, 32, 45, 32,
+ 104, 116, 116, 112, 58, 47, 47, 120, 50, 54, 53, 46, 111, 114, 103, 32, 45, 32, 111,
+ 112, 116, 105, 111, 110, 115, 58, 32, 128,
+ ];
+ match get_webcodecs_codec(codec_id, &codec_private) {
+ Ok(codec) => println!("WebCodecs codec: {}", codec),
+ Err(e) => eprintln!("Error: {}", e),
+ }
+ }
+}
diff --git a/packages/demuxing/Cargo.toml b/packages/demuxing/Cargo.toml
index 75f7d2a..7545c2b 100644
--- a/packages/demuxing/Cargo.toml
+++ b/packages/demuxing/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "demuxing"
+name = "konoplayer-demuxing"
version = "0.1.0"
edition = "2024"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0f16120..eb98867 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -31,8 +31,8 @@ importers:
specifier: 1.9.4
version: 1.9.4
'@types/node':
- specifier: ^22.13.8
- version: 22.13.9
+ specifier: ^22.13.11
+ version: 22.13.11
change-case:
specifier: ^5.4.4
version: 5.4.4
@@ -40,14 +40,14 @@ importers:
specifier: ^17.4.4
version: 17.4.4
tsx:
- specifier: ^4.19.2
+ specifier: ^4.19.3
version: 4.19.3
typescript:
specifier: ^5.8.2
version: 5.8.2
ultracite:
- specifier: ^4.1.15
- version: 4.1.20
+ specifier: ^4.2.0
+ version: 4.2.0
apps/mock:
dependencies:
@@ -72,7 +72,7 @@ importers:
devDependencies:
'@nestjs/cli':
specifier: ^11.0.0
- version: 11.0.5(@swc/cli@0.6.0(@swc/core@1.11.8(@swc/helpers@0.5.15))(chokidar@4.0.3))(@swc/core@1.11.8(@swc/helpers@0.5.15))(@types/node@22.13.9)
+ version: 11.0.5(@swc/cli@0.6.0(@swc/core@1.11.8(@swc/helpers@0.5.15))(chokidar@4.0.3))(@swc/core@1.11.8(@swc/helpers@0.5.15))(@types/node@22.13.11)
'@nestjs/schematics':
specifier: ^11.0.0
version: 11.0.2(chokidar@4.0.3)(typescript@5.7.3)
@@ -86,8 +86,8 @@ importers:
apps/playground:
dependencies:
konoebml:
- specifier: 0.1.1
- version: 0.1.1(arktype@2.1.10)
+ specifier: 0.1.2-rc.5
+ version: 0.1.2-rc.5(arktype@2.1.10)
lit:
specifier: ^3.2.1
version: 3.2.1
@@ -212,152 +212,152 @@ packages:
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
- '@esbuild/aix-ppc64@0.25.0':
- resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==}
+ '@esbuild/aix-ppc64@0.25.1':
+ resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
- '@esbuild/android-arm64@0.25.0':
- resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==}
+ '@esbuild/android-arm64@0.25.1':
+ resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
- '@esbuild/android-arm@0.25.0':
- resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==}
+ '@esbuild/android-arm@0.25.1':
+ resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
- '@esbuild/android-x64@0.25.0':
- resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==}
+ '@esbuild/android-x64@0.25.1':
+ resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
- '@esbuild/darwin-arm64@0.25.0':
- resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==}
+ '@esbuild/darwin-arm64@0.25.1':
+ resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-x64@0.25.0':
- resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==}
+ '@esbuild/darwin-x64@0.25.1':
+ resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
- '@esbuild/freebsd-arm64@0.25.0':
- resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==}
+ '@esbuild/freebsd-arm64@0.25.1':
+ resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.25.0':
- resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==}
+ '@esbuild/freebsd-x64@0.25.1':
+ resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
- '@esbuild/linux-arm64@0.25.0':
- resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==}
+ '@esbuild/linux-arm64@0.25.1':
+ resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm@0.25.0':
- resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==}
+ '@esbuild/linux-arm@0.25.1':
+ resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
- '@esbuild/linux-ia32@0.25.0':
- resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==}
+ '@esbuild/linux-ia32@0.25.1':
+ resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
- '@esbuild/linux-loong64@0.25.0':
- resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==}
+ '@esbuild/linux-loong64@0.25.1':
+ resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
- '@esbuild/linux-mips64el@0.25.0':
- resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==}
+ '@esbuild/linux-mips64el@0.25.1':
+ resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-ppc64@0.25.0':
- resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==}
+ '@esbuild/linux-ppc64@0.25.1':
+ resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-riscv64@0.25.0':
- resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==}
+ '@esbuild/linux-riscv64@0.25.1':
+ resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-s390x@0.25.0':
- resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==}
+ '@esbuild/linux-s390x@0.25.1':
+ resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
- '@esbuild/linux-x64@0.25.0':
- resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==}
+ '@esbuild/linux-x64@0.25.1':
+ resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
- '@esbuild/netbsd-arm64@0.25.0':
- resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==}
+ '@esbuild/netbsd-arm64@0.25.1':
+ resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.25.0':
- resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==}
+ '@esbuild/netbsd-x64@0.25.1':
+ resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
- '@esbuild/openbsd-arm64@0.25.0':
- resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==}
+ '@esbuild/openbsd-arm64@0.25.1':
+ resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.25.0':
- resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==}
+ '@esbuild/openbsd-x64@0.25.1':
+ resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
- '@esbuild/sunos-x64@0.25.0':
- resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==}
+ '@esbuild/sunos-x64@0.25.1':
+ resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
- '@esbuild/win32-arm64@0.25.0':
- resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==}
+ '@esbuild/win32-arm64@0.25.1':
+ resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
- '@esbuild/win32-ia32@0.25.0':
- resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==}
+ '@esbuild/win32-ia32@0.25.1':
+ resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
- '@esbuild/win32-x64@0.25.0':
- resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==}
+ '@esbuild/win32-x64@0.25.1':
+ resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -926,8 +926,8 @@ packages:
'@types/lodash@4.17.16':
resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==}
- '@types/node@22.13.9':
- resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==}
+ '@types/node@22.13.11':
+ resolution: {integrity: sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==}
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
@@ -1471,8 +1471,8 @@ packages:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'}
- esbuild@0.25.0:
- resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==}
+ esbuild@0.25.1:
+ resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==}
engines: {node: '>=18'}
hasBin: true
@@ -1866,8 +1866,8 @@ packages:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
- konoebml@0.1.1:
- resolution: {integrity: sha512-JuQnHgsoDrschZetWaZfHfTmjCXFV3B31f5Y+FzfHsFs1lQKGNH0ILj+IpyItnuq1KFwkGbslc9EBxY0CDWTFw==}
+ konoebml@0.1.2-rc.5:
+ resolution: {integrity: sha512-VsXIlsXby0OzSzLER6ERRZE+9kLkqrYUF7Wr9MKAt8qvmUc3/YStf2SdpC2gMOtCjoyxDi7bXCQPIOHziUu4nw==}
engines: {node: '>= 18.0.0'}
peerDependencies:
arktype: ^2.0.0
@@ -2602,8 +2602,8 @@ packages:
resolution: {integrity: sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==}
engines: {node: '>=18'}
- ultracite@4.1.20:
- resolution: {integrity: sha512-3vS8st0hUa2ui9RicTepFlnh2SIdZ2dCkLq0QU6HPt0KdU19iSLak3shKm83cG3Dka2sLYNerNlWoqbKHwtphg==}
+ ultracite@4.2.0:
+ resolution: {integrity: sha512-nMytk8r18BHqiZesOZogGuSGHPrsfPbI7qewSfeRD5bKtJsTl2F/c921HjIN5Zvlv5+QZvixfF3DuHRwONv0/w==}
hasBin: true
unbzip2-stream@1.4.3:
@@ -2759,11 +2759,11 @@ snapshots:
optionalDependencies:
chokidar: 4.0.3
- '@angular-devkit/schematics-cli@19.1.8(@types/node@22.13.9)(chokidar@4.0.3)':
+ '@angular-devkit/schematics-cli@19.1.8(@types/node@22.13.11)(chokidar@4.0.3)':
dependencies:
'@angular-devkit/core': 19.1.8(chokidar@4.0.3)
'@angular-devkit/schematics': 19.1.8(chokidar@4.0.3)
- '@inquirer/prompts': 7.2.1(@types/node@22.13.9)
+ '@inquirer/prompts': 7.2.1(@types/node@22.13.11)
ansi-colors: 4.1.3
symbol-observable: 4.0.0
yargs-parser: 21.1.1
@@ -2843,102 +2843,102 @@ snapshots:
'@colors/colors@1.5.0':
optional: true
- '@esbuild/aix-ppc64@0.25.0':
+ '@esbuild/aix-ppc64@0.25.1':
optional: true
- '@esbuild/android-arm64@0.25.0':
+ '@esbuild/android-arm64@0.25.1':
optional: true
- '@esbuild/android-arm@0.25.0':
+ '@esbuild/android-arm@0.25.1':
optional: true
- '@esbuild/android-x64@0.25.0':
+ '@esbuild/android-x64@0.25.1':
optional: true
- '@esbuild/darwin-arm64@0.25.0':
+ '@esbuild/darwin-arm64@0.25.1':
optional: true
- '@esbuild/darwin-x64@0.25.0':
+ '@esbuild/darwin-x64@0.25.1':
optional: true
- '@esbuild/freebsd-arm64@0.25.0':
+ '@esbuild/freebsd-arm64@0.25.1':
optional: true
- '@esbuild/freebsd-x64@0.25.0':
+ '@esbuild/freebsd-x64@0.25.1':
optional: true
- '@esbuild/linux-arm64@0.25.0':
+ '@esbuild/linux-arm64@0.25.1':
optional: true
- '@esbuild/linux-arm@0.25.0':
+ '@esbuild/linux-arm@0.25.1':
optional: true
- '@esbuild/linux-ia32@0.25.0':
+ '@esbuild/linux-ia32@0.25.1':
optional: true
- '@esbuild/linux-loong64@0.25.0':
+ '@esbuild/linux-loong64@0.25.1':
optional: true
- '@esbuild/linux-mips64el@0.25.0':
+ '@esbuild/linux-mips64el@0.25.1':
optional: true
- '@esbuild/linux-ppc64@0.25.0':
+ '@esbuild/linux-ppc64@0.25.1':
optional: true
- '@esbuild/linux-riscv64@0.25.0':
+ '@esbuild/linux-riscv64@0.25.1':
optional: true
- '@esbuild/linux-s390x@0.25.0':
+ '@esbuild/linux-s390x@0.25.1':
optional: true
- '@esbuild/linux-x64@0.25.0':
+ '@esbuild/linux-x64@0.25.1':
optional: true
- '@esbuild/netbsd-arm64@0.25.0':
+ '@esbuild/netbsd-arm64@0.25.1':
optional: true
- '@esbuild/netbsd-x64@0.25.0':
+ '@esbuild/netbsd-x64@0.25.1':
optional: true
- '@esbuild/openbsd-arm64@0.25.0':
+ '@esbuild/openbsd-arm64@0.25.1':
optional: true
- '@esbuild/openbsd-x64@0.25.0':
+ '@esbuild/openbsd-x64@0.25.1':
optional: true
- '@esbuild/sunos-x64@0.25.0':
+ '@esbuild/sunos-x64@0.25.1':
optional: true
- '@esbuild/win32-arm64@0.25.0':
+ '@esbuild/win32-arm64@0.25.1':
optional: true
- '@esbuild/win32-ia32@0.25.0':
+ '@esbuild/win32-ia32@0.25.1':
optional: true
- '@esbuild/win32-x64@0.25.0':
+ '@esbuild/win32-x64@0.25.1':
optional: true
- '@inquirer/checkbox@4.1.3(@types/node@22.13.9)':
+ '@inquirer/checkbox@4.1.3(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
'@inquirer/figures': 1.0.11
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
ansi-escapes: 4.3.2
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/confirm@5.1.7(@types/node@22.13.9)':
+ '@inquirer/confirm@5.1.7(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/core@10.1.8(@types/node@22.13.9)':
+ '@inquirer/core@10.1.8(@types/node@22.13.11)':
dependencies:
'@inquirer/figures': 1.0.11
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
ansi-escapes: 4.3.2
cli-width: 4.1.0
mute-stream: 2.0.0
@@ -2946,107 +2946,107 @@ snapshots:
wrap-ansi: 6.2.0
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/editor@4.2.8(@types/node@22.13.9)':
+ '@inquirer/editor@4.2.8(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
external-editor: 3.1.0
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/expand@4.0.10(@types/node@22.13.9)':
+ '@inquirer/expand@4.0.10(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
'@inquirer/figures@1.0.11': {}
- '@inquirer/input@4.1.7(@types/node@22.13.9)':
+ '@inquirer/input@4.1.7(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/number@3.0.10(@types/node@22.13.9)':
+ '@inquirer/number@3.0.10(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/password@4.0.10(@types/node@22.13.9)':
+ '@inquirer/password@4.0.10(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
ansi-escapes: 4.3.2
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/prompts@7.2.1(@types/node@22.13.9)':
+ '@inquirer/prompts@7.2.1(@types/node@22.13.11)':
dependencies:
- '@inquirer/checkbox': 4.1.3(@types/node@22.13.9)
- '@inquirer/confirm': 5.1.7(@types/node@22.13.9)
- '@inquirer/editor': 4.2.8(@types/node@22.13.9)
- '@inquirer/expand': 4.0.10(@types/node@22.13.9)
- '@inquirer/input': 4.1.7(@types/node@22.13.9)
- '@inquirer/number': 3.0.10(@types/node@22.13.9)
- '@inquirer/password': 4.0.10(@types/node@22.13.9)
- '@inquirer/rawlist': 4.0.10(@types/node@22.13.9)
- '@inquirer/search': 3.0.10(@types/node@22.13.9)
- '@inquirer/select': 4.0.10(@types/node@22.13.9)
- '@types/node': 22.13.9
+ '@inquirer/checkbox': 4.1.3(@types/node@22.13.11)
+ '@inquirer/confirm': 5.1.7(@types/node@22.13.11)
+ '@inquirer/editor': 4.2.8(@types/node@22.13.11)
+ '@inquirer/expand': 4.0.10(@types/node@22.13.11)
+ '@inquirer/input': 4.1.7(@types/node@22.13.11)
+ '@inquirer/number': 3.0.10(@types/node@22.13.11)
+ '@inquirer/password': 4.0.10(@types/node@22.13.11)
+ '@inquirer/rawlist': 4.0.10(@types/node@22.13.11)
+ '@inquirer/search': 3.0.10(@types/node@22.13.11)
+ '@inquirer/select': 4.0.10(@types/node@22.13.11)
+ '@types/node': 22.13.11
- '@inquirer/prompts@7.3.2(@types/node@22.13.9)':
+ '@inquirer/prompts@7.3.2(@types/node@22.13.11)':
dependencies:
- '@inquirer/checkbox': 4.1.3(@types/node@22.13.9)
- '@inquirer/confirm': 5.1.7(@types/node@22.13.9)
- '@inquirer/editor': 4.2.8(@types/node@22.13.9)
- '@inquirer/expand': 4.0.10(@types/node@22.13.9)
- '@inquirer/input': 4.1.7(@types/node@22.13.9)
- '@inquirer/number': 3.0.10(@types/node@22.13.9)
- '@inquirer/password': 4.0.10(@types/node@22.13.9)
- '@inquirer/rawlist': 4.0.10(@types/node@22.13.9)
- '@inquirer/search': 3.0.10(@types/node@22.13.9)
- '@inquirer/select': 4.0.10(@types/node@22.13.9)
+ '@inquirer/checkbox': 4.1.3(@types/node@22.13.11)
+ '@inquirer/confirm': 5.1.7(@types/node@22.13.11)
+ '@inquirer/editor': 4.2.8(@types/node@22.13.11)
+ '@inquirer/expand': 4.0.10(@types/node@22.13.11)
+ '@inquirer/input': 4.1.7(@types/node@22.13.11)
+ '@inquirer/number': 3.0.10(@types/node@22.13.11)
+ '@inquirer/password': 4.0.10(@types/node@22.13.11)
+ '@inquirer/rawlist': 4.0.10(@types/node@22.13.11)
+ '@inquirer/search': 3.0.10(@types/node@22.13.11)
+ '@inquirer/select': 4.0.10(@types/node@22.13.11)
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/rawlist@4.0.10(@types/node@22.13.9)':
+ '@inquirer/rawlist@4.0.10(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/search@3.0.10(@types/node@22.13.9)':
+ '@inquirer/search@3.0.10(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
'@inquirer/figures': 1.0.11
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/select@4.0.10(@types/node@22.13.9)':
+ '@inquirer/select@4.0.10(@types/node@22.13.11)':
dependencies:
- '@inquirer/core': 10.1.8(@types/node@22.13.9)
+ '@inquirer/core': 10.1.8(@types/node@22.13.11)
'@inquirer/figures': 1.0.11
- '@inquirer/type': 3.0.5(@types/node@22.13.9)
+ '@inquirer/type': 3.0.5(@types/node@22.13.11)
ansi-escapes: 4.3.2
yoctocolors-cjs: 2.1.2
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
- '@inquirer/type@3.0.5(@types/node@22.13.9)':
+ '@inquirer/type@3.0.5(@types/node@22.13.11)':
optionalDependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
'@isaacs/cliui@8.0.2':
dependencies:
@@ -3176,12 +3176,12 @@ snapshots:
'@napi-rs/nice-win32-x64-msvc': 1.0.1
optional: true
- '@nestjs/cli@11.0.5(@swc/cli@0.6.0(@swc/core@1.11.8(@swc/helpers@0.5.15))(chokidar@4.0.3))(@swc/core@1.11.8(@swc/helpers@0.5.15))(@types/node@22.13.9)':
+ '@nestjs/cli@11.0.5(@swc/cli@0.6.0(@swc/core@1.11.8(@swc/helpers@0.5.15))(chokidar@4.0.3))(@swc/core@1.11.8(@swc/helpers@0.5.15))(@types/node@22.13.11)':
dependencies:
'@angular-devkit/core': 19.1.8(chokidar@4.0.3)
'@angular-devkit/schematics': 19.1.8(chokidar@4.0.3)
- '@angular-devkit/schematics-cli': 19.1.8(@types/node@22.13.9)(chokidar@4.0.3)
- '@inquirer/prompts': 7.3.2(@types/node@22.13.9)
+ '@angular-devkit/schematics-cli': 19.1.8(@types/node@22.13.11)(chokidar@4.0.3)
+ '@inquirer/prompts': 7.3.2(@types/node@22.13.11)
'@nestjs/schematics': 11.0.2(chokidar@4.0.3)(typescript@5.7.3)
ansis: 3.16.0
chokidar: 4.0.3
@@ -3447,7 +3447,7 @@ snapshots:
'@types/lodash@4.17.16': {}
- '@types/node@22.13.9':
+ '@types/node@22.13.11':
dependencies:
undici-types: 6.20.0
@@ -4014,33 +4014,33 @@ snapshots:
dependencies:
es-errors: 1.3.0
- esbuild@0.25.0:
+ esbuild@0.25.1:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.25.0
- '@esbuild/android-arm': 0.25.0
- '@esbuild/android-arm64': 0.25.0
- '@esbuild/android-x64': 0.25.0
- '@esbuild/darwin-arm64': 0.25.0
- '@esbuild/darwin-x64': 0.25.0
- '@esbuild/freebsd-arm64': 0.25.0
- '@esbuild/freebsd-x64': 0.25.0
- '@esbuild/linux-arm': 0.25.0
- '@esbuild/linux-arm64': 0.25.0
- '@esbuild/linux-ia32': 0.25.0
- '@esbuild/linux-loong64': 0.25.0
- '@esbuild/linux-mips64el': 0.25.0
- '@esbuild/linux-ppc64': 0.25.0
- '@esbuild/linux-riscv64': 0.25.0
- '@esbuild/linux-s390x': 0.25.0
- '@esbuild/linux-x64': 0.25.0
- '@esbuild/netbsd-arm64': 0.25.0
- '@esbuild/netbsd-x64': 0.25.0
- '@esbuild/openbsd-arm64': 0.25.0
- '@esbuild/openbsd-x64': 0.25.0
- '@esbuild/sunos-x64': 0.25.0
- '@esbuild/win32-arm64': 0.25.0
- '@esbuild/win32-ia32': 0.25.0
- '@esbuild/win32-x64': 0.25.0
+ '@esbuild/aix-ppc64': 0.25.1
+ '@esbuild/android-arm': 0.25.1
+ '@esbuild/android-arm64': 0.25.1
+ '@esbuild/android-x64': 0.25.1
+ '@esbuild/darwin-arm64': 0.25.1
+ '@esbuild/darwin-x64': 0.25.1
+ '@esbuild/freebsd-arm64': 0.25.1
+ '@esbuild/freebsd-x64': 0.25.1
+ '@esbuild/linux-arm': 0.25.1
+ '@esbuild/linux-arm64': 0.25.1
+ '@esbuild/linux-ia32': 0.25.1
+ '@esbuild/linux-loong64': 0.25.1
+ '@esbuild/linux-mips64el': 0.25.1
+ '@esbuild/linux-ppc64': 0.25.1
+ '@esbuild/linux-riscv64': 0.25.1
+ '@esbuild/linux-s390x': 0.25.1
+ '@esbuild/linux-x64': 0.25.1
+ '@esbuild/netbsd-arm64': 0.25.1
+ '@esbuild/netbsd-x64': 0.25.1
+ '@esbuild/openbsd-arm64': 0.25.1
+ '@esbuild/openbsd-x64': 0.25.1
+ '@esbuild/sunos-x64': 0.25.1
+ '@esbuild/win32-arm64': 0.25.1
+ '@esbuild/win32-ia32': 0.25.1
+ '@esbuild/win32-x64': 0.25.1
escalade@3.2.0: {}
@@ -4455,7 +4455,7 @@ snapshots:
jest-worker@27.5.1:
dependencies:
- '@types/node': 22.13.9
+ '@types/node': 22.13.11
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -4495,7 +4495,7 @@ snapshots:
kind-of@6.0.3: {}
- konoebml@0.1.1(arktype@2.1.10):
+ konoebml@0.1.2-rc.5(arktype@2.1.10):
dependencies:
mnemonist: 0.40.3
type-fest: 4.37.0
@@ -5177,7 +5177,7 @@ snapshots:
tsx@4.19.3:
dependencies:
- esbuild: 0.25.0
+ esbuild: 0.25.1
get-tsconfig: 4.10.0
optionalDependencies:
fsevents: 2.3.3
@@ -5209,7 +5209,7 @@ snapshots:
uint8array-extras@1.4.0: {}
- ultracite@4.1.20:
+ ultracite@4.2.0:
dependencies:
commander: 12.1.0
diff --git a/scripts/codegen-mkv.ts b/scripts/codegen-mkv.ts
index 792e178..795a39a 100644
--- a/scripts/codegen-mkv.ts
+++ b/scripts/codegen-mkv.ts
@@ -43,15 +43,15 @@ const EbmlTypeMetas = {
},
uinteger: {
code: 'Uint',
- primitive: () => 'type.number',
+ primitive: () => 'type.number.or(type.bigint)',
default: (d: string): string => d,
- primitiveStr: () => 'number',
+ primitiveStr: () => '(number | bigint)',
},
integer: {
code: 'Int',
- primitive: () => 'type.number',
+ primitive: () => 'type.number.or(type.bigint)',
default: (d: string) => d,
- primitiveStr: () => 'number',
+ primitiveStr: () => '(number | bigint)',
},
float: {
code: 'Float',
@@ -160,7 +160,7 @@ function extractElement(element: Element) {
);
assert(typeof path_ === 'string', `path of ${name} is not string ${element}`);
- const path = path_.split('\\').filter(Boolean);
+ const path = path_.replace(/\\\+/g, '\\').split('\\').filter(Boolean);
const parentPath = path.at(-2);
const prefix = path.slice(0, -1);
const level = path.length - 1;
@@ -391,7 +391,7 @@ function generateMkvSchemaHierarchy(elements_: EbmlElementType[]) {
if (v.maxOccurs !== 1) {
expr = `${expr}.array()`;
if (v.maxOccurs !== 1 && v.minOccurs === 1 && !v.default) {
- expr = `${expr}.atLeastLength(1)`
+ expr = `${expr}.atLeastLength(1)`;
}
idMulti.add(v.name);
}
@@ -401,9 +401,8 @@ function generateMkvSchemaHierarchy(elements_: EbmlElementType[]) {
} else {
childrenSchema.push(`export const ${v.name}Schema = match({
"${meta.primitiveStr(v.name)}[]": v => v.length > 0 ? v : [${meta.default(v.default)}],
-"undefined": () => [${meta.default(v.default)}],
-default: "assert"
-});`);
+default: () => [${meta.default(v.default)}],
+}).optional();`);
expr = `${v.name}Schema`;
}
} else if (!v.minOccurs) {
diff --git a/scripts/download-samples.ts b/scripts/download-samples.ts
new file mode 100644
index 0000000..402c4b3
--- /dev/null
+++ b/scripts/download-samples.ts
@@ -0,0 +1,54 @@
+import { exec } from 'node:child_process';
+import { promisify } from 'node:util';
+import path from 'node:path';
+import os from 'node:os';
+import fsp from 'node:fs/promises';
+
+
+async function downloadAndExtract() {
+ try {
+ // 目标目录
+ const targetDir = path.join(import.meta.dirname, '..', 'apps', 'mock', 'public', 'video', 'huge');
+ const url = 'https://sourceforge.net/projects/matroska/files/test_files/matroska_test_w1_1.zip/download';
+ const zipFile = 'matroska_test_w1_1.zip';
+ const platform = os.platform();
+
+ const execPromise = (cmd: string) => promisify(exec)(cmd, {
+ cwd: targetDir,
+ shell: platform === 'win32' ? 'powershell' : undefined
+ });
+
+ await fsp.mkdir(targetDir, { recursive: true })
+
+ console.log(`Working directory switched to: ${targetDir}`);
+
+ if (platform === 'win32') {
+ // Windows: 使用 PowerShell 的 Invoke-WebRequest 和 Expand-Archive
+ console.log('Downloading on Windows...');
+ await execPromise(`Invoke-WebRequest -Uri '${url}' -OutFile '${zipFile}' -UserAgent "wget"`);
+ console.log('Extracting on Windows...');
+ await execPromise(`Expand-Archive -Path '${zipFile}' -DestinationPath '.' -Force`);
+ console.log('Cleaning up...');
+ await execPromise(`rm '${zipFile}'`);
+ } else {
+ // *nix: 使用 curl 和 unzip
+ console.log('Downloading on *nix...');
+ await execPromise(`curl -L "${url}" -o "${zipFile}"`);
+ console.log('Extracting on *nix...');
+ await execPromise(`unzip -o "${zipFile}"`);
+ console.log('Cleaning up...');
+ await execPromise(`rm "${zipFile}"`);
+ }
+
+ console.log('Download and extraction completed successfully!');
+ } catch (error) {
+ console.error('An error occurred:', error);
+ throw error;
+ }
+}
+
+// 执行
+downloadAndExtract().catch((err) => {
+ console.error(err)
+ process.exit(1);
+});
\ No newline at end of file