akarisub 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,391 @@
1
+ /**
2
+ * Type definitions for AkariSub TypeScript implementation.
3
+ */
4
+
5
+ // =============================================================================
6
+ // ASS/SSA Subtitle Types
7
+ // =============================================================================
8
+
9
+ /** ASS Event (dialogue/subtitle entry) */
10
+ export interface ASSEvent {
11
+ /** Start Time of the Event (in seconds) */
12
+ Start: number
13
+ /** Duration of the Event (in seconds) */
14
+ Duration: number
15
+ /** Style name */
16
+ Style: string
17
+ /** Character name (for information only) */
18
+ Name: string
19
+ /** Left Margin override in pixels */
20
+ MarginL: number
21
+ /** Right Margin override in pixels */
22
+ MarginR: number
23
+ /** Bottom Margin override in pixels */
24
+ MarginV: number
25
+ /** Transition Effect */
26
+ Effect: string
27
+ /** Subtitle Text */
28
+ Text: string
29
+ /** Read order number */
30
+ ReadOrder: number
31
+ /** Z-index layer */
32
+ Layer: number
33
+ /** Internal index */
34
+ _index?: number
35
+ }
36
+
37
+ /** ASS Style definition */
38
+ export interface ASSStyle {
39
+ /** Style name (case sensitive) */
40
+ Name: string
41
+ /** Font family name */
42
+ FontName: string
43
+ /** Font size */
44
+ FontSize: number
45
+ /** Primary color (RGBA as uint32) */
46
+ PrimaryColour: number
47
+ /** Secondary color (RGBA as uint32) */
48
+ SecondaryColour: number
49
+ /** Outline color (RGBA as uint32) */
50
+ OutlineColour: number
51
+ /** Background/shadow color (RGBA as uint32) */
52
+ BackColour: number
53
+ /** Bold (-1 = true, 0 = false) */
54
+ Bold: number
55
+ /** Italic (-1 = true, 0 = false) */
56
+ Italic: number
57
+ /** Underline (-1 = true, 0 = false) */
58
+ Underline: number
59
+ /** StrikeOut (-1 = true, 0 = false) */
60
+ StrikeOut: number
61
+ /** Width scale (percent) */
62
+ ScaleX: number
63
+ /** Height scale (percent) */
64
+ ScaleY: number
65
+ /** Extra spacing between characters (pixels) */
66
+ Spacing: number
67
+ /** Rotation angle (degrees) */
68
+ Angle: number
69
+ /** Border style (1 = outline + shadow, 3 = opaque box) */
70
+ BorderStyle: number
71
+ /** Outline width (0-4 pixels) */
72
+ Outline: number
73
+ /** Shadow depth (0-4 pixels) */
74
+ Shadow: number
75
+ /** Alignment (1-9, numpad style) */
76
+ Alignment: number
77
+ /** Left margin (pixels) */
78
+ MarginL: number
79
+ /** Right margin (pixels) */
80
+ MarginR: number
81
+ /** Vertical margin (pixels) */
82
+ MarginV: number
83
+ /** Font encoding */
84
+ Encoding: number
85
+ /** Treat font name as pattern */
86
+ treat_fontname_as_pattern: number
87
+ /** Blur amount */
88
+ Blur: number
89
+ /** Text justification */
90
+ Justify: number
91
+ }
92
+
93
+ // =============================================================================
94
+ // Performance Stats Types
95
+ // =============================================================================
96
+
97
+ /** Performance statistics for the renderer */
98
+ export interface PerformanceStats {
99
+ /** Total frames rendered since reset */
100
+ framesRendered: number
101
+ /** Number of frames dropped */
102
+ framesDropped: number
103
+ /** Average render time in milliseconds */
104
+ avgRenderTime: number
105
+ /** Maximum render time in milliseconds */
106
+ maxRenderTime: number
107
+ /** Minimum render time in milliseconds */
108
+ minRenderTime: number
109
+ /** Last render time in milliseconds */
110
+ lastRenderTime: number
111
+ /** Estimated render FPS based on timing */
112
+ renderFps: number
113
+ /** Whether using Web Worker */
114
+ usingWorker: boolean
115
+ /** Whether offscreen rendering is enabled */
116
+ offscreenRender: boolean
117
+ /** Whether on-demand rendering is enabled */
118
+ onDemandRender: boolean
119
+ /** Number of pending render operations */
120
+ pendingRenders: number
121
+ /** Total subtitle events in current track */
122
+ totalEvents: number
123
+ /** Number of cache hits (unchanged frames) */
124
+ cacheHits: number
125
+ /** Number of cache misses (rendered frames) */
126
+ cacheMisses: number
127
+ }
128
+
129
+ // =============================================================================
130
+ // AkariSub Options Types
131
+ // =============================================================================
132
+
133
+ /** Configuration options for AkariSub */
134
+ export interface AkariSubOptions {
135
+ /** Video element to sync with and overlay */
136
+ video?: HTMLVideoElement
137
+ /** Custom canvas element (optional if video is provided) */
138
+ canvas?: HTMLCanvasElement
139
+ /** Image blending mode: 'js' for hardware acceleration, 'wasm' for software */
140
+ blendMode?: 'js' | 'wasm'
141
+ /** Use async rendering with ImageBitmap (default: true) */
142
+ asyncRender?: boolean
143
+ /** Use offscreen canvas rendering (default: true) */
144
+ offscreenRender?: boolean
145
+ /** Use requestVideoFrameCallback for precise sync (default: true) */
146
+ onDemandRender?: boolean
147
+ /** Target FPS when not using onDemandRender (default: 24) */
148
+ targetFps?: number
149
+ /** Time offset in seconds (default: 0) */
150
+ timeOffset?: number
151
+ /** Enable debug logging (default: false) */
152
+ debug?: boolean
153
+ /** Scale factor for subtitles (default: 1.0) */
154
+ prescaleFactor?: number
155
+ /** Height limit for prescaling (default: 1080) */
156
+ prescaleHeightLimit?: number
157
+ /** Maximum render height, 0 = no limit (default: 0) */
158
+ maxRenderHeight?: number
159
+ /** Attempt to drop all animations (default: false) */
160
+ dropAllAnimations?: boolean
161
+ /** Drop all blur effects for performance (default: false) */
162
+ dropAllBlur?: boolean
163
+ /** Clamp \\pos values to script resolution (default: false) */
164
+ clampPos?: boolean
165
+ /** URL to the worker script */
166
+ workerUrl?: string
167
+ /** URL to the WASM binary */
168
+ wasmUrl?: string
169
+ /** URL to subtitle file */
170
+ subUrl?: string
171
+ /** Subtitle content as string */
172
+ subContent?: string
173
+ /** Array of font URLs or Uint8Arrays */
174
+ fonts?: (string | Uint8Array)[]
175
+ /** Available fonts map (lowercase name -> URL/data) */
176
+ availableFonts?: Record<string, string | Uint8Array>
177
+ /** Fallback font families in order (default: ['liberation sans']). Fontconfig uses these for cascade. */
178
+ fallbackFonts?: string[]
179
+ /** Use Local Font Access API (default: true if available) */
180
+ useLocalFonts?: boolean
181
+ /** libass bitmap cache memory limit in MiB */
182
+ libassMemoryLimit?: number
183
+ /** libass glyph cache limit */
184
+ libassGlyphLimit?: number
185
+ /** Callback invoked when all GPU renderers (WebGPU, WebGL2) are unavailable and the renderer falls back to Canvas2D */
186
+ onCanvasFallback?: () => void
187
+ /** Additional time in seconds to render subtitles ahead for pipeline latency compensation (default: 0.008) */
188
+ renderAhead?: number
189
+ }
190
+
191
+ // =============================================================================
192
+ // Callback Types (deprecated - use Promise-based API instead)
193
+ // =============================================================================
194
+
195
+ /** @deprecated Use Promise-based getEvents() instead */
196
+ export type ASSEventCallback = (error: Error | null, events: ASSEvent[]) => void
197
+ /** @deprecated Use Promise-based getStyles() instead */
198
+ export type ASSStyleCallback = (error: Error | null, styles: ASSStyle[]) => void
199
+ /** @deprecated Use Promise-based getStats() instead */
200
+ export type PerformanceStatsCallback = (error: Error | null, stats: PerformanceStats | null) => void
201
+ /** @deprecated Use Promise-based resetStats() instead */
202
+ export type ResetStatsCallback = (error: Error | null) => void
203
+
204
+ // =============================================================================
205
+ // Worker Message Types
206
+ // =============================================================================
207
+
208
+ /** Image data for rendering */
209
+ export interface RenderImage {
210
+ x: number
211
+ y: number
212
+ w: number
213
+ h: number
214
+ image: ImageBitmap | ArrayBuffer | number
215
+ }
216
+
217
+ /** Render timing debug info */
218
+ export interface RenderTimes {
219
+ WASMRenderTime?: number
220
+ WASMBitmapDecodeTime?: number
221
+ JSRenderTime?: number
222
+ JSBitmapGenerationTime?: number
223
+ IPCTime?: number
224
+ bitmaps?: number
225
+ }
226
+
227
+ /** Worker -> Main thread message for rendering */
228
+ export interface RenderMessage {
229
+ target: 'render'
230
+ asyncRender: boolean
231
+ images: RenderImage[]
232
+ times: RenderTimes
233
+ width: number
234
+ height: number
235
+ colorSpace: string | null
236
+ }
237
+
238
+ /** Worker -> Main thread messages */
239
+ export type WorkerOutboundMessage =
240
+ | { target: 'ready' }
241
+ | { target: 'unbusy' }
242
+ | { target: 'console'; command: string; content: string }
243
+ | { target: 'getLocalFont'; font: string }
244
+ | { target: 'verifyColorSpace'; subtitleColorSpace: string | null }
245
+ | { target: 'getEvents'; events: ASSEvent[] }
246
+ | { target: 'getStyles'; styles: ASSStyle[]; time: number }
247
+ | { target: 'getStats'; stats: Partial<PerformanceStats> }
248
+ | { target: 'resetStats'; success: boolean }
249
+ | { target: 'getEventCount'; count: number }
250
+ | { target: 'getStyleCount'; count: number }
251
+ | RenderMessage
252
+
253
+ /** Main thread -> Worker init message */
254
+ export interface WorkerInitMessage {
255
+ target: 'init'
256
+ wasmUrl: string
257
+ asyncRender: boolean
258
+ onDemandRender: boolean
259
+ initialTime: number
260
+ width: number
261
+ height: number
262
+ blendMode: 'js' | 'wasm'
263
+ subUrl?: string
264
+ subContent?: string | null
265
+ fonts: (string | Uint8Array)[]
266
+ availableFonts: Record<string, string | Uint8Array>
267
+ fallbackFonts: string[]
268
+ debug: boolean
269
+ targetFps: number
270
+ dropAllAnimations?: boolean
271
+ dropAllBlur?: boolean
272
+ clampPos?: boolean
273
+ libassMemoryLimit?: number
274
+ libassGlyphLimit?: number
275
+ useLocalFonts: boolean
276
+ hasBitmapBug: boolean
277
+ }
278
+
279
+ /** Main thread -> Worker messages */
280
+ export type WorkerInboundMessage =
281
+ | WorkerInitMessage
282
+ | { target: 'offscreenCanvas'; transferable: [OffscreenCanvas] }
283
+ | { target: 'detachOffscreen' }
284
+ | { target: 'canvas'; width: number; height: number; videoWidth: number; videoHeight: number; force?: boolean }
285
+ | { target: 'video'; currentTime?: number; isPaused?: boolean; rate?: number; colorSpace?: string | null }
286
+ | { target: 'setTrack'; content: string }
287
+ | { target: 'setTrackByUrl'; url: string }
288
+ | { target: 'freeTrack' }
289
+ | { target: 'demand'; time: number }
290
+ | { target: 'destroy' }
291
+ | { target: 'addFont'; font: string | Uint8Array }
292
+ | { target: 'defaultFont'; font: string }
293
+ | { target: 'createEvent'; event: Partial<ASSEvent> }
294
+ | { target: 'setEvent'; event: Partial<ASSEvent>; index: number }
295
+ | { target: 'removeEvent'; index: number }
296
+ | { target: 'getEvents' }
297
+ | { target: 'createStyle'; style: Partial<ASSStyle> }
298
+ | { target: 'setStyle'; style: Partial<ASSStyle>; index: number }
299
+ | { target: 'removeStyle'; index: number }
300
+ | { target: 'getStyles' }
301
+ | { target: 'styleOverride'; style: Partial<ASSStyle> }
302
+ | { target: 'disableStyleOverride' }
303
+ | { target: 'getStats' }
304
+ | { target: 'resetStats' }
305
+ | { target: 'getEventCount' }
306
+ | { target: 'getStyleCount' }
307
+ | { target: 'runBenchmark' }
308
+ | { target: 'getColorSpace' }
309
+
310
+ // =============================================================================
311
+ // RVFC Types
312
+ // =============================================================================
313
+
314
+ /** requestVideoFrameCallback metadata */
315
+ export interface VideoFrameCallbackMetadata {
316
+ /** The current media time of the frame being displayed (seconds) */
317
+ mediaTime: number
318
+ /** Video intrinsic width */
319
+ width: number
320
+ /** Video intrinsic height */
321
+ height: number
322
+ /** Number of frames presented so far */
323
+ presentedFrames?: number
324
+ /** Time spent processing the frame (milliseconds) */
325
+ processingDuration?: number
326
+ /** Expected time when this frame will be displayed (DOMHighResTimeStamp) */
327
+ expectedDisplayTime?: number
328
+ /** Time at which the frame was presented (DOMHighResTimeStamp) */
329
+ presentationTime?: number
330
+ }
331
+
332
+ // =============================================================================
333
+ // Color Space Types
334
+ // =============================================================================
335
+
336
+ export type WebYCbCrColorSpace = 'BT709' | 'BT601'
337
+ export type SubtitleColorSpace = 'BT601' | 'BT709' | 'SMPTE240M' | 'FCC' | null
338
+
339
+ // =============================================================================
340
+ // AkariSub WASM Module Types
341
+ // =============================================================================
342
+
343
+ /** Emscripten AkariSub Module (C ABI exports) */
344
+ export interface AkariSubModule extends EmscriptenModule {
345
+ _malloc: (size: number) => number
346
+ _free: (ptr: number) => void
347
+ _akarisub_create: (width: number, height: number, fallbackFontPtr: number, debug: number) => number
348
+ _akarisub_destroy: (handle: number) => void
349
+ _akarisub_set_drop_animations: (handle: number, value: number) => void
350
+ _akarisub_create_track_mem: (handle: number, contentPtr: number) => void
351
+ _akarisub_remove_track: (handle: number) => void
352
+ _akarisub_resize_canvas: (handle: number, width: number, height: number, videoWidth: number, videoHeight: number) => void
353
+ _akarisub_add_font: (handle: number, namePtr: number, dataPtr: number, size: number) => void
354
+ _akarisub_reload_fonts: (handle: number) => void
355
+ _akarisub_set_default_font: (handle: number, fontPtr: number) => void
356
+ _akarisub_set_fallback_fonts: (handle: number, fontsPtr: number) => void
357
+ _akarisub_set_memory_limits: (handle: number, glyphLimit: number, memoryLimit: number) => void
358
+ _akarisub_get_event_count: (handle: number) => number
359
+ _akarisub_alloc_event: (handle: number) => number
360
+ _akarisub_remove_event: (handle: number, index: number) => void
361
+ _akarisub_get_style_count: (handle: number) => number
362
+ _akarisub_alloc_style: (handle: number) => number
363
+ _akarisub_remove_style: (handle: number, index: number) => void
364
+ _akarisub_style_override_index: (handle: number, index: number) => void
365
+ _akarisub_disable_style_override: (handle: number) => void
366
+ _akarisub_render_blend: (handle: number, time: number, force: number) => number
367
+ _akarisub_render_image: (handle: number, time: number, force: number) => number
368
+ _akarisub_get_changed: (handle: number) => number
369
+ _akarisub_get_count: (handle: number) => number
370
+ _akarisub_get_time: (handle: number) => number
371
+ _akarisub_get_track_color_space: (handle: number) => number
372
+ _akarisub_event_get_int: (handle: number, index: number, field: number) => number
373
+ _akarisub_event_set_int: (handle: number, index: number, field: number, value: number) => void
374
+ _akarisub_event_get_str: (handle: number, index: number, field: number) => number
375
+ _akarisub_event_set_str: (handle: number, index: number, field: number, valuePtr: number) => void
376
+ _akarisub_style_get_num: (handle: number, index: number, field: number) => number
377
+ _akarisub_style_set_num: (handle: number, index: number, field: number, value: number) => void
378
+ _akarisub_style_get_str: (handle: number, index: number, field: number) => number
379
+ _akarisub_style_set_str: (handle: number, index: number, field: number, valuePtr: number) => void
380
+ _akarisub_render_result_x: (resultPtr: number) => number
381
+ _akarisub_render_result_y: (resultPtr: number) => number
382
+ _akarisub_render_result_w: (resultPtr: number) => number
383
+ _akarisub_render_result_h: (resultPtr: number) => number
384
+ _akarisub_render_result_image: (resultPtr: number) => number
385
+ _akarisub_render_result_next: (resultPtr: number) => number
386
+ _akarisub_render_result_collect: (resultPtr: number, outPtr: number, maxItems: number) => number
387
+ _akarisub_render_blend_collect: (handle: number, time: number, force: number, outPtr: number, maxItems: number) => number
388
+ _akarisub_render_image_collect: (handle: number, time: number, force: number, outPtr: number, maxItems: number) => number
389
+ FS_createPath: (parent: string, path: string, canRead: boolean, canWrite: boolean) => void
390
+ FS_createDataFile: (parent: string, name: string | null, data: Uint8Array, canRead: boolean, canWrite: boolean, canOwn?: boolean) => void
391
+ }