feat: temp save

This commit is contained in:
2025-03-21 13:54:39 +08:00
parent 4537190096
commit d7b8b57e9c
8 changed files with 62 additions and 130 deletions

View File

@@ -2,7 +2,6 @@ import {
type EbmlTagType,
EbmlTagIdEnum,
EbmlTagPosition,
type EbmlCuePointTagType,
type EbmlTracksTagType,
type EbmlInfoTagType,
type EbmlCuesTagType,
@@ -127,13 +126,11 @@ export class TrackEntry extends TagWithArktype({
}),
}) {}
const TracksSchema = type({
tracks: type.instanceOf(TrackEntry).array(),
});
export class Tracks extends TagWithArktype({
id: EbmlTagIdEnum.Tracks,
schema: TracksSchema,
schema: type({
tracks: type.instanceOf(TrackEntry).array(),
}),
extract: simpleMasterExtractor({
[EbmlTagIdEnum.TrackEntry]: {
key: 'tracks',
@@ -148,13 +145,11 @@ export interface EbmlSeekEntry {
seekPosition: number;
}
export class EbmlHead {
head: EbmlTagType;
constructor(head: EbmlTagType) {
this.head = head;
}
}
export class MHead extends TagWithArktype({
id: EbmlTagIdEnum.EBML,
schema: type({}),
extract: () => ({}),
}) {}
export class SimpleBlock extends TagWithArktype({
id: EbmlTagIdEnum.SimpleBlock,
@@ -166,6 +161,12 @@ export class SimpleBlock extends TagWithArktype({
}),
}) {}
export class Block extends TagWithArktype({
id: EbmlTagIdEnum.Block,
schema: type({}),
extract: () => ({}),
}) {}
export class Cluster extends TagWithArktype({
id: EbmlTagIdEnum.Cluster,
schema: type({
@@ -191,88 +192,16 @@ export class Cluster extends TagWithArktype({
}),
}) {}
export interface TrackPositions {
track: number;
clusterPosition: number;
relativePosition?: number;
duration?: number;
}
export type CuePointType = typeof CuePoint.infer;
export class CuePoint {
node: EbmlCuePointTagType;
_timestamp: number;
trackPositions: TrackPositions[];
export class Cues {
cues: CuePointType[];
get timestamp(): number {
return this._timestamp;
}
constructor(
public readonly tag: EbmlCuesTagType,
cues: CuePointType[]
) {}
get position(): number {
return Math.max(...this.trackPositions.map((t) => t.clusterPosition));
}
constructor(node: EbmlCuePointTagType) {
this.node = node;
this._timestamp = node.children.find((c) => c.id === EbmlTagIdEnum.CueTime)
?.data as number;
this.trackPositions = node.children
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: <explanation>
.map((t) => {
if (
t.id === EbmlTagIdEnum.CueTrackPositions &&
t.position === EbmlTagPosition.End
) {
let track!: number;
let clusterPosition!: number;
let relativePosition: number | undefined;
let duration: number | undefined;
for (const c of t.children) {
if (c.id === EbmlTagIdEnum.CueTrack) {
track = c.data as number;
}
if (c.id === EbmlTagIdEnum.CueClusterPosition) {
clusterPosition = c.data as number;
}
if (c.id === EbmlTagIdEnum.CueRelativePosition) {
relativePosition = c.data as number;
}
if (c.id === EbmlTagIdEnum.CueDuration) {
duration = c.data as number;
}
}
if (track! >= 0 && clusterPosition! >= 0) {
return {
track: track!,
clusterPosition: clusterPosition!,
relativePosition,
duration,
} as TrackPositions;
}
throw new Error(
`Tracking positions missing track of cluster position at ${t.startOffset}`
);
}
return null;
})
.filter((a): a is TrackPositions => !!a);
}
}
export class Cues extends TagWithArktype({
id: EbmlTagIdEnum.Cues,
schema: type({
cues: type.instanceOf(CuePoint).array(),
}),
extract: simpleMasterExtractor({
[EbmlTagIdEnum.CuePoint]: {
key: 'cues',
multi: true,
extract: (t) => new CuePoint(t),
},
}),
}) {
findClosestCue(seekTime: number): CuePoint | null {
const cues = this.cues;
if (!cues || cues.length === 0) {
@@ -282,22 +211,22 @@ export class Cues extends TagWithArktype({
let left = 0;
let right = cues.length - 1;
if (seekTime <= cues[0].timestamp) {
if (seekTime <= cues[0].CueTime) {
return cues[0];
}
if (seekTime >= cues[right].timestamp) {
if (seekTime >= cues[right].CueTime) {
return cues[right];
}
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (cues[mid].timestamp === seekTime) {
if (cues[mid].CueTime === seekTime) {
return cues[mid];
}
if (cues[mid].timestamp < seekTime) {
if (cues[mid].CueTime < seekTime) {
left = mid + 1;
} else {
right = mid - 1;

View File

View File

@@ -4,65 +4,56 @@ import type { EbmlMasterTagType, EbmlTagIdEnum, EbmlTagType } from 'konoebml';
export type InferType<T> = T extends Type<infer U> ? U : never;
export interface TagWithArktypeOptions<
I extends EbmlTagType['id'],
T extends EbmlTagType,
S extends Type<any>,
> {
id: I;
id: T['id'];
schema: S;
extract: (tag: Extract<EbmlTagType, { id: I }>, schema: S) => InferType<S>;
extract: (tag: T, schema: S) => InferType<S>;
}
export type TagWithArktypeClassInstance<
I extends EbmlTagType['id'],
T extends EbmlTagType,
S extends Type<any>,
> = InferType<S> & {
tag: Extract<EbmlTagType, { id: I }>;
tag: T;
};
export interface TagWithArktypeClass<
I extends EbmlTagType['id'],
T extends EbmlTagType,
S extends Type<any>,
> {
new (
tag: Extract<EbmlTagType, { id: I }>,
validatedTag: InferType<S>
): TagWithArktypeClassInstance<I, S>;
new (tag: T, validatedTag: InferType<S>): TagWithArktypeClassInstance<T, S>;
fromTag<R extends TagWithArktypeClassInstance<I, S>>(
fromTag<R extends TagWithArktypeClassInstance<T, S>>(
this: new (
tag: Extract<EbmlTagType, { id: I }>,
tag: T,
validatedTag: InferType<S>
) => TagWithArktypeClassInstance<I, S>,
tag: Extract<EbmlTagType, { id: I }>
) => TagWithArktypeClassInstance<T, S>,
tag: T
): R;
id: I;
id: T['id'];
schema: S;
}
export function TagWithArktype<
I extends EbmlTagType['id'],
S extends Type<any>,
>({
export function TagWithArktype<T extends EbmlTagType, S extends Type<any>>({
id,
schema,
extract,
}: TagWithArktypeOptions<I, S>): TagWithArktypeClass<I, S> {
}: TagWithArktypeOptions<T, S>): TagWithArktypeClass<T, S> {
const tagWithArktypeImpl = class TagWithArktypeImpl {
static id = id;
static schema = schema;
tag: Extract<EbmlTagType, { id: I }>;
tag: T;
constructor(
tag: Extract<EbmlTagType, { id: I }>,
validatedTag: InferType<S>
) {
constructor(tag: T, validatedTag: InferType<S>) {
Object.assign(this, validatedTag);
this.tag = tag;
}
static fromTag(tag: Extract<EbmlTagType, { id: I }>) {
static fromTag(tag: T) {
const extractedData = extract(tag, schema);
const validatedExtractedData = schema(extractedData);
// biome-ignore lint/complexity/noThisInStatic: <explanation>
@@ -70,7 +61,7 @@ export function TagWithArktype<
}
};
return tagWithArktypeImpl as unknown as TagWithArktypeClass<I, S>;
return tagWithArktypeImpl as unknown as TagWithArktypeClass<T, S>;
}
export type PredicateIdExtract<T, K> = Extract<T, { id: K }>;