0
# Debug and Inspection Tools
1
2
Comprehensive debugging utilities for MP4, FLV, and transport stream inspection. These tools are essential for troubleshooting streaming issues, understanding media structure, and debugging transmuxing problems.
3
4
## Capabilities
5
6
### MP4 Inspection Tools
7
8
Complete MP4 debugging and analysis utilities for understanding MP4 box structure and content.
9
10
```javascript { .api }
11
/**
12
* MP4 inspection and debugging tools
13
*/
14
const mp4Tools: {
15
/** Inspect MP4 structure and parse all boxes */
16
inspect(data: Uint8Array): MP4Structure;
17
18
/** Convert MP4 structure to human-readable text representation */
19
textify(structure: MP4Structure): string;
20
21
/** Parse MP4 box type from binary data */
22
parseType(data: Uint8Array): string;
23
24
/** Find specific box type in MP4 data */
25
findBox(data: Uint8Array, boxType: string): Uint8Array | null;
26
27
/** Parse track fragment (traf) box */
28
parseTraf(data: Uint8Array): TrafBox;
29
30
/** Parse track fragment decode time (tfdt) box */
31
parseTfdt(data: Uint8Array): TfdtBox;
32
33
/** Parse handler (hdlr) box */
34
parseHdlr(data: Uint8Array): HdlrBox;
35
36
/** Parse track fragment header (tfhd) box */
37
parseTfhd(data: Uint8Array): TfhdBox;
38
39
/** Parse track run (trun) box */
40
parseTrun(data: Uint8Array): TrunBox;
41
42
/** Parse segment index (sidx) box */
43
parseSidx(data: Uint8Array): SidxBox;
44
45
/** Parse sample flags from trun box */
46
parseSampleFlags(flags: number): SampleFlags;
47
};
48
49
interface MP4Structure {
50
boxes: MP4Box[];
51
totalSize: number;
52
}
53
54
interface MP4Box {
55
type: string;
56
size: number;
57
offset: number;
58
data: Uint8Array;
59
children?: MP4Box[];
60
}
61
```
62
63
**Usage Examples:**
64
65
```javascript
66
const muxjs = require("mux.js");
67
68
// Inspect MP4 file structure
69
const mp4Data = new Uint8Array([/* MP4 file data */]);
70
const structure = muxjs.mp4.tools.inspect(mp4Data);
71
72
console.log('MP4 Analysis:');
73
console.log(`Total size: ${structure.totalSize} bytes`);
74
console.log(`Root boxes: ${structure.boxes.length}`);
75
76
// List all boxes
77
structure.boxes.forEach(box => {
78
console.log(`Box: ${box.type}, size: ${box.size} bytes`);
79
if (box.children) {
80
box.children.forEach(child => {
81
console.log(` Child: ${child.type}, size: ${child.size} bytes`);
82
});
83
}
84
});
85
86
// Get human-readable representation
87
const textOutput = muxjs.mp4.tools.textify(structure);
88
console.log('MP4 Structure:');
89
console.log(textOutput);
90
91
// Find specific boxes
92
const moovBox = muxjs.mp4.tools.findBox(mp4Data, 'moov');
93
if (moovBox) {
94
console.log('Found movie box');
95
96
// Parse handler box to identify track type
97
const hdlrBox = muxjs.mp4.tools.findBox(moovBox, 'hdlr');
98
if (hdlrBox) {
99
const handler = muxjs.mp4.tools.parseHdlr(hdlrBox);
100
console.log(`Track handler: ${handler.handlerType}`);
101
}
102
}
103
104
// Analyze fragmented MP4
105
const moofBox = muxjs.mp4.tools.findBox(mp4Data, 'moof');
106
if (moofBox) {
107
console.log('Found movie fragment');
108
109
// Parse track fragment
110
const trafBox = muxjs.mp4.tools.findBox(moofBox, 'traf');
111
if (trafBox) {
112
const traf = muxjs.mp4.tools.parseTraf(trafBox);
113
console.log(`Track fragment for track ${traf.trackId}`);
114
115
// Parse decode time
116
const tfdtData = muxjs.mp4.tools.findBox(trafBox, 'tfdt');
117
if (tfdtData) {
118
const tfdt = muxjs.mp4.tools.parseTfdt(tfdtData);
119
console.log(`Base media decode time: ${tfdt.baseMediaDecodeTime}`);
120
}
121
}
122
}
123
```
124
125
### Transport Stream Inspection Tools
126
127
Tools for analyzing MPEG-2 transport stream structure and content.
128
129
```javascript { .api }
130
/**
131
* Transport stream inspection and debugging tools
132
*/
133
const mp2tTools: {
134
/** Inspect transport stream structure and packets */
135
inspect(data: Uint8Array): TransportStreamStructure;
136
};
137
138
interface TransportStreamStructure {
139
packets: TransportPacketInfo[];
140
programs: ProgramInfo[];
141
streams: StreamInfo[];
142
totalPackets: number;
143
}
144
145
interface TransportPacketInfo {
146
pid: number;
147
payloadUnitStartIndicator: boolean;
148
adaptationFieldControl: number;
149
continuityCounter: number;
150
payload: Uint8Array;
151
}
152
153
interface ProgramInfo {
154
programNumber: number;
155
pmtPid: number;
156
streams: StreamInfo[];
157
}
158
159
interface StreamInfo {
160
pid: number;
161
streamType: number;
162
streamTypeDescription: string;
163
elementaryPidCount: number;
164
}
165
```
166
167
**Usage Examples:**
168
169
```javascript
170
const muxjs = require("mux.js");
171
172
// Inspect transport stream
173
const tsData = new Uint8Array([/* Transport stream data */]);
174
const tsStructure = muxjs.mp2t.tools.inspect(tsData);
175
176
console.log('Transport Stream Analysis:');
177
console.log(`Total packets: ${tsStructure.totalPackets}`);
178
console.log(`Programs: ${tsStructure.programs.length}`);
179
console.log(`Streams: ${tsStructure.streams.length}`);
180
181
// Analyze programs
182
tsStructure.programs.forEach(program => {
183
console.log(`Program ${program.programNumber}:`);
184
console.log(` PMT PID: 0x${program.pmtPid.toString(16)}`);
185
186
program.streams.forEach(stream => {
187
console.log(` Stream PID: 0x${stream.pid.toString(16)}`);
188
console.log(` Type: ${stream.streamTypeDescription} (0x${stream.streamType.toString(16)})`);
189
console.log(` Packet count: ${stream.elementaryPidCount}`);
190
});
191
});
192
193
// Analyze packet distribution
194
const pidCounts = {};
195
tsStructure.packets.forEach(packet => {
196
pidCounts[packet.pid] = (pidCounts[packet.pid] || 0) + 1;
197
});
198
199
console.log('Packet distribution by PID:');
200
Object.entries(pidCounts).forEach(([pid, count]) => {
201
console.log(` PID 0x${parseInt(pid).toString(16)}: ${count} packets`);
202
});
203
```
204
205
### FLV Inspection Tools
206
207
Tools for analyzing FLV file structure and tags.
208
209
```javascript { .api }
210
/**
211
* FLV inspection and debugging tools
212
*/
213
const flvTools: {
214
/** Inspect individual FLV tag structure */
215
inspectTag(data: Uint8Array): FlvTagInfo;
216
217
/** Inspect complete FLV file structure */
218
inspect(data: Uint8Array): FlvStructure;
219
220
/** Convert FLV structure to human-readable text */
221
textify(structure: FlvStructure): string;
222
};
223
224
interface FlvTagInfo {
225
tagType: number;
226
tagTypeDescription: string;
227
dataSize: number;
228
timestamp: number;
229
timestampExtended: number;
230
streamId: number;
231
data: Uint8Array;
232
}
233
234
interface FlvStructure {
235
header: FlvHeader;
236
tags: FlvTagInfo[];
237
totalSize: number;
238
duration: number;
239
}
240
241
interface FlvHeader {
242
signature: string;
243
version: number;
244
flags: {
245
audio: boolean;
246
video: boolean;
247
};
248
headerSize: number;
249
}
250
```
251
252
**Usage Examples:**
253
254
```javascript
255
const muxjs = require("mux.js");
256
257
// Inspect FLV file
258
const flvData = new Uint8Array([/* FLV file data */]);
259
const flvStructure = muxjs.flv.tools.inspect(flvData);
260
261
console.log('FLV Analysis:');
262
console.log(`Version: ${flvStructure.header.version}`);
263
console.log(`Has audio: ${flvStructure.header.flags.audio}`);
264
console.log(`Has video: ${flvStructure.header.flags.video}`);
265
console.log(`Duration: ${flvStructure.duration}ms`);
266
console.log(`Total tags: ${flvStructure.tags.length}`);
267
268
// Analyze tag types
269
const tagTypeCounts = {};
270
flvStructure.tags.forEach(tag => {
271
const type = tag.tagTypeDescription;
272
tagTypeCounts[type] = (tagTypeCounts[type] || 0) + 1;
273
});
274
275
console.log('Tag distribution:');
276
Object.entries(tagTypeCounts).forEach(([type, count]) => {
277
console.log(` ${type}: ${count} tags`);
278
});
279
280
// Get readable representation
281
const textOutput = muxjs.flv.tools.textify(flvStructure);
282
console.log('FLV Structure:');
283
console.log(textOutput);
284
285
// Inspect specific tag
286
const firstVideoTag = flvStructure.tags.find(tag => tag.tagType === 9);
287
if (firstVideoTag) {
288
const tagInfo = muxjs.flv.tools.inspectTag(firstVideoTag.data);
289
console.log('First video tag:', tagInfo);
290
}
291
```
292
293
## Debugging Workflows
294
295
### Transmuxing Debug Workflow
296
297
Common workflow for debugging transmuxing issues:
298
299
```javascript
300
const muxjs = require("mux.js");
301
302
function debugTransmuxing(transportStreamData) {
303
console.log('=== Transport Stream Analysis ===');
304
305
// 1. Inspect input transport stream
306
const tsStructure = muxjs.mp2t.tools.inspect(transportStreamData);
307
console.log(`Input: ${tsStructure.totalPackets} packets`);
308
console.log(`Programs: ${tsStructure.programs.length}`);
309
310
// 2. Set up transmuxer with debugging
311
const transmuxer = new muxjs.mp4.Transmuxer();
312
313
transmuxer.on('data', (segment) => {
314
console.log('=== MP4 Output Analysis ===');
315
316
// Inspect initialization segment
317
if (segment.initSegment.length > 0) {
318
const initStructure = muxjs.mp4.tools.inspect(segment.initSegment);
319
console.log('Init segment boxes:');
320
initStructure.boxes.forEach(box => {
321
console.log(` ${box.type}: ${box.size} bytes`);
322
});
323
}
324
325
// Inspect media segment
326
const mediaStructure = muxjs.mp4.tools.inspect(segment.data);
327
console.log('Media segment boxes:');
328
mediaStructure.boxes.forEach(box => {
329
console.log(` ${box.type}: ${box.size} bytes`);
330
});
331
332
// Check for captions
333
console.log(`Captions: ${segment.captions.length}`);
334
segment.captions.forEach(captionSet => {
335
console.log(` ${captionSet.content.length} captions from ${captionSet.startTime}s to ${captionSet.endTime}s`);
336
});
337
338
// Check metadata
339
console.log(`Metadata frames: ${segment.metadata.frames.length}`);
340
});
341
342
// 3. Process data
343
transmuxer.push(transportStreamData);
344
transmuxer.flush();
345
}
346
347
// Usage
348
debugTransmuxing(transportStreamData);
349
```
350
351
### MP4 Structure Analysis
352
353
Detailed MP4 structure analysis for troubleshooting:
354
355
```javascript
356
function analyzeMP4Structure(mp4Data) {
357
const structure = muxjs.mp4.tools.inspect(mp4Data);
358
359
console.log('=== MP4 Structure Analysis ===');
360
361
// Check for required boxes
362
const requiredBoxes = ['ftyp', 'moov'];
363
const foundBoxes = structure.boxes.map(box => box.type);
364
365
requiredBoxes.forEach(required => {
366
if (foundBoxes.includes(required)) {
367
console.log(`✓ Found required box: ${required}`);
368
} else {
369
console.log(`✗ Missing required box: ${required}`);
370
}
371
});
372
373
// Analyze tracks
374
const moovBox = muxjs.mp4.tools.findBox(mp4Data, 'moov');
375
if (moovBox) {
376
const trakBoxes = [];
377
let offset = 8; // Skip box header
378
379
while (offset < moovBox.length) {
380
const boxType = muxjs.mp4.tools.parseType(moovBox.subarray(offset + 4, offset + 8));
381
if (boxType === 'trak') {
382
trakBoxes.push(moovBox.subarray(offset));
383
}
384
385
const size = new DataView(moovBox.buffer, moovBox.byteOffset + offset).getUint32(0);
386
offset += size;
387
}
388
389
console.log(`Tracks found: ${trakBoxes.length}`);
390
391
trakBoxes.forEach((trakBox, index) => {
392
const hdlrBox = muxjs.mp4.tools.findBox(trakBox, 'hdlr');
393
if (hdlrBox) {
394
const handler = muxjs.mp4.tools.parseHdlr(hdlrBox);
395
console.log(` Track ${index + 1}: ${handler.handlerType}`);
396
}
397
});
398
}
399
400
// Check for fragmentation
401
const hasFragments = foundBoxes.includes('moof');
402
console.log(`Fragmented MP4: ${hasFragments ? 'Yes' : 'No'}`);
403
404
return structure;
405
}
406
```
407
408
## Advanced Debugging Features
409
410
### Box-Level Analysis
411
412
```javascript
413
// Detailed box analysis
414
function analyzeBox(boxData, boxType) {
415
console.log(`=== ${boxType.toUpperCase()} Box Analysis ===`);
416
417
switch (boxType) {
418
case 'tfhd':
419
const tfhd = muxjs.mp4.tools.parseTfhd(boxData);
420
console.log(`Track ID: ${tfhd.trackId}`);
421
console.log(`Base data offset: ${tfhd.baseDataOffset}`);
422
break;
423
424
case 'trun':
425
const trun = muxjs.mp4.tools.parseTrun(boxData);
426
console.log(`Sample count: ${trun.sampleCount}`);
427
console.log(`Data offset: ${trun.dataOffset}`);
428
break;
429
430
case 'sidx':
431
const sidx = muxjs.mp4.tools.parseSidx(boxData);
432
console.log(`Reference ID: ${sidx.referenceId}`);
433
console.log(`Timescale: ${sidx.timescale}`);
434
break;
435
}
436
}
437
```
438
439
### Performance Monitoring
440
441
```javascript
442
// Performance monitoring during inspection
443
function monitoredInspect(data, format) {
444
const startTime = performance.now();
445
446
let result;
447
switch (format) {
448
case 'mp4':
449
result = muxjs.mp4.tools.inspect(data);
450
break;
451
case 'flv':
452
result = muxjs.flv.tools.inspect(data);
453
break;
454
case 'ts':
455
result = muxjs.mp2t.tools.inspect(data);
456
break;
457
}
458
459
const endTime = performance.now();
460
console.log(`${format.toUpperCase()} inspection took ${endTime - startTime}ms`);
461
462
return result;
463
}
464
```
465
466
## Types
467
468
```javascript { .api }
469
interface TrafBox {
470
trackId: number;
471
baseDataOffset?: number;
472
sampleDescriptionIndex?: number;
473
defaultSampleDuration?: number;
474
defaultSampleSize?: number;
475
defaultSampleFlags?: number;
476
}
477
478
interface TfdtBox {
479
version: number;
480
baseMediaDecodeTime: number;
481
}
482
483
interface HdlrBox {
484
handlerType: string;
485
name: string;
486
}
487
488
interface TfhdBox {
489
trackId: number;
490
baseDataOffset?: number;
491
sampleDescriptionIndex?: number;
492
defaultSampleDuration?: number;
493
defaultSampleSize?: number;
494
defaultSampleFlags?: number;
495
}
496
497
interface TrunBox {
498
sampleCount: number;
499
dataOffset?: number;
500
firstSampleFlags?: number;
501
samples: TrunSample[];
502
}
503
504
interface TrunSample {
505
duration?: number;
506
size?: number;
507
flags?: number;
508
compositionTimeOffset?: number;
509
}
510
511
interface SidxBox {
512
referenceId: number;
513
timescale: number;
514
earliestPresentationTime: number;
515
firstOffset: number;
516
references: SidxReference[];
517
}
518
519
interface SidxReference {
520
referenceType: number;
521
referencedSize: number;
522
subsegmentDuration: number;
523
startsWithSap: boolean;
524
sapType: number;
525
sapDeltaTime: number;
526
}
527
528
interface SampleFlags {
529
isLeading: number;
530
dependsOn: number;
531
isDependedOn: number;
532
hasRedundancy: number;
533
degradPrio: number;
534
isNonSync: boolean;
535
}
536
```