tirtc-devtools-cli 0.0.13 → 0.0.14

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.
Files changed (137) hide show
  1. package/README.md +42 -46
  2. package/USAGE.md +87 -312
  3. package/dist/cli/src/embedded_paths.d.ts +0 -2
  4. package/dist/cli/src/embedded_paths.js +3 -25
  5. package/dist/cli/src/index.js +82 -584
  6. package/dist/cli/src/role_driver.d.ts +33 -0
  7. package/dist/cli/src/role_driver.js +500 -0
  8. package/dist/cli/src/token_command.js +4 -2
  9. package/dist/cli/src/token_issue.d.ts +9 -0
  10. package/dist/cli/src/token_issue.js +138 -0
  11. package/dist/cli/src/token_tool.d.ts +2 -4
  12. package/dist/cli/src/token_tool.js +12 -186
  13. package/package.json +1 -1
  14. package/vendor/devtools/driver/macos-arm64/devtools_driver_probe +0 -0
  15. package/vendor/devtools/driver/macos-arm64/runtime_validation_client_bin +0 -0
  16. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio.h +56 -2
  17. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io.h +9 -0
  18. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/av.h +52 -0
  19. package/vendor/{app-server/bin/runtime/linux-x64 → runtime/macos-arm64}/include/tirtc/error.h +11 -0
  20. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/media_downlink.h +11 -5
  21. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/media_uplink.h +4 -0
  22. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/transport.h +52 -15
  23. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/trp.h +7 -5
  24. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_codec.h +41 -0
  25. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io.h +7 -0
  26. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io_android.h +2 -0
  27. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libmatrix_runtime_audio.a +0 -0
  28. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
  29. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libmatrix_runtime_foundation_http.a +0 -0
  30. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  31. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
  32. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
  33. package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
  34. package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/manifest.txt +20 -25
  35. package/vendor/runtime/script/prepare_runtime_media_dataset.sh +308 -12
  36. package/dist/app-server/protocol-client/index.d.ts +0 -25
  37. package/dist/app-server/protocol-client/index.js +0 -114
  38. package/dist/cli/src/bootstrap_flows.d.ts +0 -46
  39. package/dist/cli/src/bootstrap_flows.js +0 -249
  40. package/dist/cli/src/config.d.ts +0 -26
  41. package/dist/cli/src/config.js +0 -62
  42. package/dist/cli/src/facade.d.ts +0 -430
  43. package/dist/cli/src/facade.js +0 -170
  44. package/dist/cli/src/guide.d.ts +0 -1
  45. package/dist/cli/src/guide.js +0 -48
  46. package/dist/cli/src/session_manager.d.ts +0 -25
  47. package/dist/cli/src/session_manager.js +0 -391
  48. package/dist/cli/src/transport.d.ts +0 -30
  49. package/dist/cli/src/transport.js +0 -84
  50. package/vendor/app-server/bin/native/linux-x64/credential_napi.node +0 -0
  51. package/vendor/app-server/bin/native/macos-arm64/credential_napi.node +0 -0
  52. package/vendor/app-server/bin/runtime/linux-x64/include/tirtc/credential.h +0 -34
  53. package/vendor/app-server/bin/runtime/linux-x64/lib/libcrypto.a +0 -0
  54. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_credential.a +0 -0
  55. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_foundation_http.a +0 -0
  56. package/vendor/app-server/bin/runtime/linux-x64/lib/libmatrix_runtime_foundation_logging.a +0 -0
  57. package/vendor/app-server/bin/runtime/linux-x64/lib/libssl.a +0 -0
  58. package/vendor/app-server/bin/runtime/linux-x64/lib/libxlog.a +0 -0
  59. package/vendor/app-server/bin/runtime/linux-x64/manifest.txt +0 -4
  60. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/credential.h +0 -34
  61. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/error.h +0 -52
  62. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/foundation/build_info.h +0 -27
  63. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/http.h +0 -57
  64. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/logging.h +0 -55
  65. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/media_fixture_av_sync.h +0 -61
  66. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/media_fixture_source.h +0 -77
  67. package/vendor/app-server/bin/runtime/macos-arm64/include/tirtc/media_live_source.h +0 -71
  68. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_credential.a +0 -0
  69. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
  70. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
  71. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
  72. package/vendor/app-server/bin/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
  73. package/vendor/app-server/bin/tirtc-devtool-host.js +0 -2
  74. package/vendor/app-server/dist/host/ArtifactManager.d.ts +0 -18
  75. package/vendor/app-server/dist/host/ArtifactManager.js +0 -98
  76. package/vendor/app-server/dist/host/HostCommandCoordinator.d.ts +0 -19
  77. package/vendor/app-server/dist/host/HostCommandCoordinator.js +0 -196
  78. package/vendor/app-server/dist/host/HostProtocol.d.ts +0 -103
  79. package/vendor/app-server/dist/host/HostProtocol.js +0 -239
  80. package/vendor/app-server/dist/host/HostServer.d.ts +0 -52
  81. package/vendor/app-server/dist/host/HostServer.js +0 -727
  82. package/vendor/app-server/dist/host/HostState.d.ts +0 -69
  83. package/vendor/app-server/dist/host/HostState.js +0 -19
  84. package/vendor/app-server/dist/host/RuntimeAdapter.d.ts +0 -95
  85. package/vendor/app-server/dist/host/RuntimeAdapter.js +0 -636
  86. package/vendor/app-server/dist/host/RuntimeReceiveWorker.d.ts +0 -37
  87. package/vendor/app-server/dist/host/RuntimeReceiveWorker.js +0 -186
  88. package/vendor/app-server/dist/host/RuntimeSendWorker.d.ts +0 -58
  89. package/vendor/app-server/dist/host/RuntimeSendWorker.js +0 -438
  90. package/vendor/app-server/dist/host/TokenTool.d.ts +0 -15
  91. package/vendor/app-server/dist/host/TokenTool.js +0 -84
  92. package/vendor/app-server/dist/host/WebPreviewGateway.d.ts +0 -28
  93. package/vendor/app-server/dist/host/WebPreviewGateway.js +0 -815
  94. package/vendor/app-server/dist/host/native/RuntimeCredentialTokenIssuer.d.ts +0 -23
  95. package/vendor/app-server/dist/host/native/RuntimeCredentialTokenIssuer.js +0 -115
  96. package/vendor/app-server/dist/host/native/RuntimeHostBridge.d.ts +0 -32
  97. package/vendor/app-server/dist/host/native/RuntimeHostBridge.js +0 -157
  98. package/vendor/app-server/dist/host/runtime_backed_preflight.d.ts +0 -10
  99. package/vendor/app-server/dist/host/runtime_backed_preflight.js +0 -78
  100. package/vendor/app-server/dist/host/tests/helpers/host_socket_client.d.ts +0 -28
  101. package/vendor/app-server/dist/host/tests/helpers/host_socket_client.js +0 -85
  102. package/vendor/app-server/dist/host/tests/helpers/runtime_e2e_local_config.d.ts +0 -10
  103. package/vendor/app-server/dist/host/tests/helpers/runtime_e2e_local_config.js +0 -41
  104. package/vendor/app-server/dist/host/tests/helpers/runtime_test_env.d.ts +0 -11
  105. package/vendor/app-server/dist/host/tests/helpers/runtime_test_env.js +0 -32
  106. package/vendor/app-server/dist/protocol/contract.d.ts +0 -1128
  107. package/vendor/app-server/dist/protocol/contract.js +0 -217
  108. package/vendor/app-server/dist/protocol-client/index.d.ts +0 -25
  109. package/vendor/app-server/dist/protocol-client/index.js +0 -114
  110. package/vendor/app-server/dist/src/index.d.ts +0 -1
  111. package/vendor/app-server/dist/src/index.js +0 -294
  112. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_codec.h +0 -0
  113. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_frame.h +0 -0
  114. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io_android.h +0 -0
  115. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io_apple.h +0 -0
  116. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io_harmony.h +0 -0
  117. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_io_windows.h +0 -0
  118. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_processing.h +0 -0
  119. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/audio_sample_rate.h +0 -0
  120. /package/vendor/{app-server/bin/runtime/linux-x64 → runtime/macos-arm64}/include/tirtc/foundation/build_info.h +0 -0
  121. /package/vendor/{app-server/bin/runtime/linux-x64 → runtime/macos-arm64}/include/tirtc/http.h +0 -0
  122. /package/vendor/{app-server/bin/runtime/linux-x64 → runtime/macos-arm64}/include/tirtc/logging.h +0 -0
  123. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/media_codec.h +0 -0
  124. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_frame.h +0 -0
  125. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io_apple.h +0 -0
  126. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io_harmony.h +0 -0
  127. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_io_windows.h +0 -0
  128. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/include/tirtc/video_processing.h +0 -0
  129. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libTGTRP.a +0 -0
  130. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libTiRTC.a +0 -0
  131. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libcrypto.a +0 -0
  132. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libcrypto.dylib +0 -0
  133. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libssl.a +0 -0
  134. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libssl.dylib +0 -0
  135. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libtgrtc.dylib +0 -0
  136. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libwebrtc_apm.a +0 -0
  137. /package/vendor/{app-server/bin/runtime → runtime}/macos-arm64/lib/libxlog.a +0 -0
@@ -129,16 +129,18 @@ require_cmd "$FFPROBE_BIN"
129
129
  SOURCE_ABS="$(cd "$(dirname "$SOURCE")" && pwd)/$(basename "$SOURCE")"
130
130
  SOURCE_FILE_NAME="$(basename "$SOURCE_ABS")"
131
131
 
132
- readonly k_schema_version=1
133
- readonly k_tool_version="runtime_local_assets_prepare_v4"
132
+ readonly k_schema_version=2
133
+ readonly k_tool_version="runtime_local_assets_prepare_v5"
134
134
  readonly k_video_max_width=1280
135
135
  readonly k_video_max_height=720
136
136
  readonly k_video_fps=15
137
137
  readonly k_audio_sample_rate_hz=8000
138
+ readonly k_audio_sample_rate_16k_hz=16000
138
139
  readonly k_audio_channels=1
139
140
  readonly k_audio_packet_duration_ms=40
141
+ readonly k_mjpeg_packet_duration_ms=80
142
+ readonly k_mjpeg_extract_interval_seconds=10
140
143
  readonly k_loop_policy="continuous_pts"
141
- readonly k_video_codec="h264_annexb"
142
144
  readonly k_audio_codec="g711a"
143
145
  readonly k_output_audio_format="pcm_s16"
144
146
  readonly k_output_video_format="rgba8888"
@@ -224,10 +226,16 @@ fi
224
226
  mkdir -p "$ASSETS_DIR/video"
225
227
  mkdir -p "$ASSETS_DIR/audio"
226
228
 
227
- VIDEO_PATH="$ASSETS_DIR/video/video.h264"
228
- VIDEO_PACKET_INDEX_PATH="$ASSETS_DIR/video/video_packets.csv"
229
+ VIDEO_H264_PATH="$ASSETS_DIR/video/video.h264"
230
+ VIDEO_H264_PACKET_INDEX_PATH="$ASSETS_DIR/video/video_packets.csv"
231
+ VIDEO_H265_PATH="$ASSETS_DIR/video/video.h265"
232
+ VIDEO_H265_PACKET_INDEX_PATH="$ASSETS_DIR/video/video_h265_packets.csv"
233
+ VIDEO_MJPEG_PATH="$ASSETS_DIR/video/video.mjpeg"
234
+ VIDEO_MJPEG_PACKET_INDEX_PATH="$ASSETS_DIR/video/video_mjpeg_packets.csv"
229
235
  AUDIO_PATH="$ASSETS_DIR/audio/audio.g711a"
230
236
  AUDIO_PACKET_INDEX_PATH="$ASSETS_DIR/audio/audio_packets.csv"
237
+ AUDIO_16K_PATH="$ASSETS_DIR/audio/audio_16k.g711a"
238
+ AUDIO_16K_PACKET_INDEX_PATH="$ASSETS_DIR/audio/audio_16k_packets.csv"
231
239
 
232
240
  video_encode_args=(
233
241
  -vf "fps=${k_video_fps},scale=${TARGET_VIDEO_WIDTH}:${TARGET_VIDEO_HEIGHT}:flags=lanczos"
@@ -256,7 +264,52 @@ fi
256
264
  -an \
257
265
  "${video_encode_args[@]}" \
258
266
  -f h264 \
259
- "$VIDEO_PATH"
267
+ "$VIDEO_H264_PATH"
268
+
269
+ video_h265_encode_args=(
270
+ -vf "fps=${k_video_fps},scale=${TARGET_VIDEO_WIDTH}:${TARGET_VIDEO_HEIGHT}:flags=lanczos"
271
+ -c:v libx265
272
+ -preset medium
273
+ -pix_fmt yuv420p
274
+ -bf 0
275
+ -g "${k_video_fps}"
276
+ -keyint_min "${k_video_fps}"
277
+ -sc_threshold 0
278
+ -x265-params "repeat-headers=1:aud=1:keyint=${k_video_fps}:min-keyint=${k_video_fps}:scenecut=0"
279
+ )
280
+ if [[ "$TARGET_VIDEO_BITRATE_KBPS" -gt 0 ]]; then
281
+ video_h265_encode_args+=(
282
+ -b:v "${TARGET_VIDEO_BITRATE_KBPS}k"
283
+ -maxrate "${TARGET_VIDEO_BITRATE_KBPS}k"
284
+ -bufsize "$((TARGET_VIDEO_BITRATE_KBPS * 2))k"
285
+ )
286
+ else
287
+ video_h265_encode_args+=(-crf 23)
288
+ fi
289
+
290
+ "$FFMPEG_BIN" -hide_banner -loglevel error -y \
291
+ -i "$SOURCE_ABS" \
292
+ -an \
293
+ "${video_h265_encode_args[@]}" \
294
+ -f hevc \
295
+ "$VIDEO_H265_PATH"
296
+
297
+ mjpeg_frame_dir="$ASSETS_DIR/video/mjpeg_frames"
298
+ mkdir -p "$mjpeg_frame_dir"
299
+ "$FFMPEG_BIN" -hide_banner -loglevel error -y \
300
+ -i "$SOURCE_ABS" \
301
+ -vf "fps=1/${k_mjpeg_extract_interval_seconds},scale=${TARGET_VIDEO_WIDTH}:${TARGET_VIDEO_HEIGHT}:flags=lanczos" \
302
+ -q:v 4 \
303
+ "$mjpeg_frame_dir/frame_%06d.jpg"
304
+
305
+ if ! find "$mjpeg_frame_dir" -type f -name 'frame_*.jpg' | grep -q .; then
306
+ "$FFMPEG_BIN" -hide_banner -loglevel error -y \
307
+ -i "$SOURCE_ABS" \
308
+ -frames:v 1 \
309
+ -vf "scale=${TARGET_VIDEO_WIDTH}:${TARGET_VIDEO_HEIGHT}:flags=lanczos" \
310
+ -q:v 4 \
311
+ "$mjpeg_frame_dir/frame_000001.jpg"
312
+ fi
260
313
 
261
314
  "$FFMPEG_BIN" -hide_banner -loglevel error -y \
262
315
  -i "$SOURCE_ABS" \
@@ -267,15 +320,123 @@ fi
267
320
  -f alaw \
268
321
  "$AUDIO_PATH"
269
322
 
270
- VIDEO_PACKET_INDEX_PATH="$VIDEO_PACKET_INDEX_PATH" \
271
- VIDEO_PATH="$VIDEO_PATH" \
323
+ "$FFMPEG_BIN" -hide_banner -loglevel error -y \
324
+ -i "$SOURCE_ABS" \
325
+ -vn \
326
+ -ac ${k_audio_channels} \
327
+ -ar ${k_audio_sample_rate_16k_hz} \
328
+ -c:a pcm_alaw \
329
+ -f alaw \
330
+ "$AUDIO_16K_PATH"
331
+
332
+ VIDEO_PACKET_INDEX_PATH="$VIDEO_H264_PACKET_INDEX_PATH" \
333
+ VIDEO_PATH="$VIDEO_H264_PATH" \
334
+ VIDEO_FPS="$k_video_fps" \
335
+ VIDEO_CODEC="h264" \
336
+ node <<'NODE'
337
+ const fs = require('fs');
338
+
339
+ const videoPath = process.env.VIDEO_PATH;
340
+ const outputPath = process.env.VIDEO_PACKET_INDEX_PATH;
341
+ const fps = Number(process.env.VIDEO_FPS || '15');
342
+ const codec = process.env.VIDEO_CODEC || 'h264';
343
+
344
+ if (!videoPath || !outputPath || !Number.isFinite(fps) || fps <= 0) {
345
+ throw new Error('video packet index env is incomplete');
346
+ }
347
+
348
+ const data = fs.readFileSync(videoPath);
349
+ const starts = [];
350
+ for (let index = 0; index < data.length - 3; index += 1) {
351
+ if (data[index] === 0 && data[index + 1] === 0) {
352
+ if (data[index + 2] === 1) {
353
+ starts.push({offset: index, prefix: 3});
354
+ index += 2;
355
+ continue;
356
+ }
357
+ if (index + 3 < data.length && data[index + 2] === 0 && data[index + 3] === 1) {
358
+ starts.push({offset: index, prefix: 4});
359
+ index += 3;
360
+ }
361
+ }
362
+ }
363
+
364
+ if (starts.length === 0) {
365
+ throw new Error('video bitstream missing annexb start codes');
366
+ }
367
+
368
+ const packetOffsets = [];
369
+ let currentPacketStart = 0;
370
+ let currentPacketHasData = false;
371
+ let currentPacketKeyFrame = false;
372
+
373
+ for (let index = 0; index < starts.length; index += 1) {
374
+ const start = starts[index];
375
+ const nextOffset = index + 1 < starts.length ? starts[index + 1].offset : data.length;
376
+ const nalHeaderOffset = start.offset + start.prefix;
377
+ if (nalHeaderOffset >= nextOffset) {
378
+ continue;
379
+ }
380
+
381
+ const nalType = codec === 'h265' ? ((data[nalHeaderOffset] >> 1) & 0x3f) : (data[nalHeaderOffset] & 0x1f);
382
+ const isAccessUnitDelimiter = codec === 'h265' ? nalType === 35 : nalType === 9;
383
+ const isKeyFrame = codec === 'h265' ? nalType >= 16 && nalType <= 21 : nalType === 5;
384
+ if (isAccessUnitDelimiter) {
385
+ if (currentPacketHasData) {
386
+ packetOffsets.push({
387
+ offset: currentPacketStart,
388
+ size: start.offset - currentPacketStart,
389
+ keyFrame: currentPacketKeyFrame,
390
+ });
391
+ }
392
+ currentPacketStart = start.offset;
393
+ currentPacketHasData = true;
394
+ currentPacketKeyFrame = false;
395
+ continue;
396
+ }
397
+
398
+ if (!currentPacketHasData) {
399
+ currentPacketStart = start.offset;
400
+ currentPacketHasData = true;
401
+ currentPacketKeyFrame = false;
402
+ }
403
+ if (isKeyFrame) {
404
+ currentPacketKeyFrame = true;
405
+ }
406
+ }
407
+
408
+ if (currentPacketHasData && currentPacketStart < data.length) {
409
+ packetOffsets.push({
410
+ offset: currentPacketStart,
411
+ size: data.length - currentPacketStart,
412
+ keyFrame: currentPacketKeyFrame,
413
+ });
414
+ }
415
+
416
+ if (packetOffsets.length === 0) {
417
+ throw new Error('video packet index is empty');
418
+ }
419
+
420
+ const frameDurationUs = Math.round(1_000_000 / fps);
421
+ const lines = ['pts_us,offset,size,is_key_frame'];
422
+ for (let index = 0; index < packetOffsets.length; index += 1) {
423
+ const entry = packetOffsets[index];
424
+ lines.push(`${index * frameDurationUs},${entry.offset},${entry.size},${entry.keyFrame ? 1 : 0}`);
425
+ }
426
+ fs.writeFileSync(outputPath, `${lines.join('\n')}\n`, 'utf8');
427
+ NODE
428
+
429
+ VIDEO_PACKET_INDEX_PATH="$VIDEO_H265_PACKET_INDEX_PATH" \
430
+ VIDEO_PATH="$VIDEO_H265_PATH" \
272
431
  VIDEO_FPS="$k_video_fps" \
432
+ VIDEO_CODEC="h265" \
273
433
  node <<'NODE'
274
434
  const fs = require('fs');
275
435
 
276
436
  const videoPath = process.env.VIDEO_PATH;
277
437
  const outputPath = process.env.VIDEO_PACKET_INDEX_PATH;
278
438
  const fps = Number(process.env.VIDEO_FPS || '15');
439
+ const codec = process.env.VIDEO_CODEC || 'h264';
279
440
 
280
441
  if (!videoPath || !outputPath || !Number.isFinite(fps) || fps <= 0) {
281
442
  throw new Error('video packet index env is incomplete');
@@ -314,8 +475,10 @@ for (let index = 0; index < starts.length; index += 1) {
314
475
  continue;
315
476
  }
316
477
 
317
- const nalType = data[nalHeaderOffset] & 0x1f;
318
- if (nalType === 9) {
478
+ const nalType = codec === 'h265' ? ((data[nalHeaderOffset] >> 1) & 0x3f) : (data[nalHeaderOffset] & 0x1f);
479
+ const isAccessUnitDelimiter = codec === 'h265' ? nalType === 35 : nalType === 9;
480
+ const isKeyFrame = codec === 'h265' ? nalType >= 16 && nalType <= 21 : nalType === 5;
481
+ if (isAccessUnitDelimiter) {
319
482
  if (currentPacketHasData) {
320
483
  packetOffsets.push({
321
484
  offset: currentPacketStart,
@@ -334,7 +497,7 @@ for (let index = 0; index < starts.length; index += 1) {
334
497
  currentPacketHasData = true;
335
498
  currentPacketKeyFrame = false;
336
499
  }
337
- if (nalType === 5) {
500
+ if (isKeyFrame) {
338
501
  currentPacketKeyFrame = true;
339
502
  }
340
503
  }
@@ -360,6 +523,61 @@ for (let index = 0; index < packetOffsets.length; index += 1) {
360
523
  fs.writeFileSync(outputPath, `${lines.join('\n')}\n`, 'utf8');
361
524
  NODE
362
525
 
526
+ VIDEO_MJPEG_PATH="$VIDEO_MJPEG_PATH" \
527
+ VIDEO_MJPEG_PACKET_INDEX_PATH="$VIDEO_MJPEG_PACKET_INDEX_PATH" \
528
+ MJPEG_FRAME_DIR="$mjpeg_frame_dir" \
529
+ H264_PACKET_INDEX_PATH="$VIDEO_H264_PACKET_INDEX_PATH" \
530
+ MJPEG_PACKET_DURATION_MS="$k_mjpeg_packet_duration_ms" \
531
+ node <<'NODE'
532
+ const fs = require('fs');
533
+ const path = require('path');
534
+
535
+ const frameDir = process.env.MJPEG_FRAME_DIR;
536
+ const outputPath = process.env.VIDEO_MJPEG_PATH;
537
+ const indexPath = process.env.VIDEO_MJPEG_PACKET_INDEX_PATH;
538
+ const h264IndexPath = process.env.H264_PACKET_INDEX_PATH;
539
+ const packetDurationMs = Number(process.env.MJPEG_PACKET_DURATION_MS || '80');
540
+ if (!frameDir || !outputPath || !indexPath || !h264IndexPath || !Number.isFinite(packetDurationMs) || packetDurationMs <= 0) {
541
+ throw new Error('mjpeg packet index env is incomplete');
542
+ }
543
+
544
+ const frameFiles = fs.readdirSync(frameDir)
545
+ .filter((name) => /^frame_\d+\.jpg$/.test(name))
546
+ .sort()
547
+ .map((name) => path.join(frameDir, name));
548
+ if (frameFiles.length === 0) {
549
+ throw new Error('mjpeg frames are empty');
550
+ }
551
+
552
+ const offsets = [];
553
+ let cursor = 0;
554
+ const chunks = [];
555
+ for (const frameFile of frameFiles) {
556
+ const data = fs.readFileSync(frameFile);
557
+ if (data.length === 0) {
558
+ throw new Error(`empty mjpeg frame: ${frameFile}`);
559
+ }
560
+ offsets.push({offset: cursor, size: data.length});
561
+ chunks.push(data);
562
+ cursor += data.length;
563
+ }
564
+ fs.writeFileSync(outputPath, Buffer.concat(chunks));
565
+
566
+ const h264Rows = fs.readFileSync(h264IndexPath, 'utf8').trim().split(/\r?\n/).slice(1);
567
+ const h264PacketCount = Math.max(1, h264Rows.length);
568
+ const durationUs = Math.max(1_000_000, Math.ceil(h264PacketCount * 1_000_000 / 15));
569
+ const packetDurationUs = packetDurationMs * 1000;
570
+ const packetCount = Math.max(1, Math.ceil(durationUs / packetDurationUs));
571
+ const lines = ['pts_us,offset,size,is_key_frame'];
572
+ for (let index = 0; index < packetCount; index += 1) {
573
+ const ptsUs = index * packetDurationUs;
574
+ const frameIndex = Math.floor(ptsUs / 1_000_000) % offsets.length;
575
+ const entry = offsets[frameIndex];
576
+ lines.push(`${ptsUs},${entry.offset},${entry.size},1`);
577
+ }
578
+ fs.writeFileSync(indexPath, `${lines.join('\n')}\n`, 'utf8');
579
+ NODE
580
+
363
581
  AUDIO_BYTES="$(wc -c < "$AUDIO_PATH" | tr -d '[:space:]')"
364
582
  AUDIO_PACKET_BYTES=$((k_audio_sample_rate_hz * k_audio_packet_duration_ms / 1000))
365
583
  [[ "$AUDIO_PACKET_BYTES" -gt 0 ]] || fail "invalid audio packet bytes"
@@ -391,6 +609,37 @@ AUDIO_PACKET_COUNT=$((AUDIO_BYTES / AUDIO_PACKET_BYTES))
391
609
  done
392
610
  } > "$AUDIO_PACKET_INDEX_PATH"
393
611
 
612
+ AUDIO_16K_BYTES="$(wc -c < "$AUDIO_16K_PATH" | tr -d '[:space:]')"
613
+ AUDIO_16K_PACKET_BYTES=$((k_audio_sample_rate_16k_hz * k_audio_packet_duration_ms / 1000))
614
+ [[ "$AUDIO_16K_PACKET_BYTES" -gt 0 ]] || fail "invalid 16k audio packet bytes"
615
+ AUDIO_16K_REMAINDER=$((AUDIO_16K_BYTES % AUDIO_16K_PACKET_BYTES))
616
+ if [[ "$AUDIO_16K_REMAINDER" -ne 0 ]]; then
617
+ AUDIO_16K_ALIGNED_BYTES=$((AUDIO_16K_BYTES - AUDIO_16K_REMAINDER))
618
+ [[ "$AUDIO_16K_ALIGNED_BYTES" -gt 0 ]] || fail "16k audio output is too short for one full packet"
619
+ echo "[prepare_runtime_media_dataset] trim trailing 16k audio bytes to packet boundary: removed=${AUDIO_16K_REMAINDER}" >&2
620
+ AUDIO_PATH="$AUDIO_16K_PATH" AUDIO_ALIGNED_BYTES="$AUDIO_16K_ALIGNED_BYTES" node <<'NODE'
621
+ const fs = require('fs');
622
+ const audioPath = process.env.AUDIO_PATH;
623
+ const alignedBytes = Number(process.env.AUDIO_ALIGNED_BYTES || '0');
624
+ if (!audioPath || !Number.isFinite(alignedBytes) || alignedBytes <= 0) {
625
+ throw new Error('audio trim env is incomplete');
626
+ }
627
+ fs.truncateSync(audioPath, alignedBytes);
628
+ NODE
629
+ AUDIO_16K_BYTES="$AUDIO_16K_ALIGNED_BYTES"
630
+ fi
631
+ AUDIO_16K_PACKET_COUNT=$((AUDIO_16K_BYTES / AUDIO_16K_PACKET_BYTES))
632
+ [[ "$AUDIO_16K_PACKET_COUNT" -gt 0 ]] || fail "generated 16k audio packets are empty"
633
+
634
+ {
635
+ echo "pts_us,offset,size"
636
+ for ((i = 0; i < AUDIO_16K_PACKET_COUNT; i += 1)); do
637
+ pts_us=$((i * k_audio_packet_duration_ms * 1000))
638
+ offset=$((i * AUDIO_16K_PACKET_BYTES))
639
+ echo "${pts_us},${offset},${AUDIO_16K_PACKET_BYTES}"
640
+ done
641
+ } > "$AUDIO_16K_PACKET_INDEX_PATH"
642
+
394
643
  cat > "$MANIFEST_PATH" <<JSON
395
644
  {
396
645
  "schema_version": ${k_schema_version},
@@ -402,7 +651,7 @@ cat > "$MANIFEST_PATH" <<JSON
402
651
  "video": {
403
652
  "path": "video/video.h264",
404
653
  "packet_index_path": "video/video_packets.csv",
405
- "codec": "${k_video_codec}",
654
+ "codec": "h264_annexb",
406
655
  "width": ${TARGET_VIDEO_WIDTH},
407
656
  "height": ${TARGET_VIDEO_HEIGHT},
408
657
  "fps": ${k_video_fps},
@@ -420,6 +669,53 @@ cat > "$MANIFEST_PATH" <<JSON
420
669
  "audio_format": "${k_output_audio_format}",
421
670
  "video_format": "${k_output_video_format}"
422
671
  },
672
+ "video_tracks": {
673
+ "h264_annexb": {
674
+ "path": "video/video.h264",
675
+ "packet_index_path": "video/video_packets.csv",
676
+ "codec": "h264_annexb",
677
+ "width": ${TARGET_VIDEO_WIDTH},
678
+ "height": ${TARGET_VIDEO_HEIGHT},
679
+ "fps_num": ${k_video_fps},
680
+ "fps_den": 1
681
+ },
682
+ "h265_annexb": {
683
+ "path": "video/video.h265",
684
+ "packet_index_path": "video/video_h265_packets.csv",
685
+ "codec": "h265_annexb",
686
+ "width": ${TARGET_VIDEO_WIDTH},
687
+ "height": ${TARGET_VIDEO_HEIGHT},
688
+ "fps_num": ${k_video_fps},
689
+ "fps_den": 1
690
+ },
691
+ "mjpeg_jfif": {
692
+ "path": "video/video.mjpeg",
693
+ "packet_index_path": "video/video_mjpeg_packets.csv",
694
+ "codec": "mjpeg_jfif",
695
+ "width": ${TARGET_VIDEO_WIDTH},
696
+ "height": ${TARGET_VIDEO_HEIGHT},
697
+ "fps_num": 1000,
698
+ "fps_den": ${k_mjpeg_packet_duration_ms}
699
+ }
700
+ },
701
+ "audio_tracks": {
702
+ "g711a_8k": {
703
+ "path": "audio/audio.g711a",
704
+ "packet_index_path": "audio/audio_packets.csv",
705
+ "codec": "${k_audio_codec}",
706
+ "sample_rate_hz": ${k_audio_sample_rate_hz},
707
+ "channels": ${k_audio_channels},
708
+ "packet_duration_ms": ${k_audio_packet_duration_ms}
709
+ },
710
+ "g711a_16k": {
711
+ "path": "audio/audio_16k.g711a",
712
+ "packet_index_path": "audio/audio_16k_packets.csv",
713
+ "codec": "${k_audio_codec}",
714
+ "sample_rate_hz": ${k_audio_sample_rate_16k_hz},
715
+ "channels": ${k_audio_channels},
716
+ "packet_duration_ms": ${k_audio_packet_duration_ms}
717
+ }
718
+ },
423
719
  "loop_policy": "${k_loop_policy}"
424
720
  }
425
721
  JSON
@@ -1,25 +0,0 @@
1
- import { EventEmitter } from 'events';
2
- export interface Transport {
3
- send(data: string): void;
4
- onMessage(handler: (data: string) => void): void;
5
- onClose(handler: () => void): void;
6
- onError(handler: (error: Error) => void): void;
7
- }
8
- export declare class AppServerClient extends EventEmitter {
9
- private transport;
10
- private pendingRequests;
11
- initialized: boolean;
12
- private buffer;
13
- constructor(transport: Transport);
14
- private rejectAllPending;
15
- private handleData;
16
- private handleMessage;
17
- sendRequest(method: string, params?: unknown, timeoutMs?: number): Promise<unknown>;
18
- sendNotification(method: string, params?: unknown): void;
19
- initialize(clientInfo: {
20
- name: string;
21
- version: string;
22
- title?: string;
23
- }, capabilities?: unknown): Promise<unknown>;
24
- subscribeEvents(families: string[]): Promise<unknown>;
25
- }
@@ -1,114 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AppServerClient = void 0;
4
- const events_1 = require("events");
5
- const crypto_1 = require("crypto");
6
- class AppServerClient extends events_1.EventEmitter {
7
- transport;
8
- pendingRequests;
9
- initialized = false;
10
- buffer = '';
11
- constructor(transport) {
12
- super();
13
- this.transport = transport;
14
- this.pendingRequests = new Map();
15
- this.transport.onMessage((data) => this.handleData(data));
16
- this.transport.onError((error) => {
17
- this.emit('error', error);
18
- this.rejectAllPending(error);
19
- });
20
- this.transport.onClose(() => {
21
- const error = new Error('transport closed');
22
- this.emit('close');
23
- this.rejectAllPending(error);
24
- });
25
- }
26
- rejectAllPending(error) {
27
- for (const [id, req] of this.pendingRequests.entries()) {
28
- this.pendingRequests.delete(id);
29
- if (req.timeoutTimer) {
30
- clearTimeout(req.timeoutTimer);
31
- }
32
- req.reject(error);
33
- }
34
- }
35
- handleData(chunk) {
36
- this.buffer += chunk;
37
- const lines = this.buffer.split('\n');
38
- this.buffer = lines.pop() || '';
39
- for (const line of lines) {
40
- if (!line.trim()) {
41
- continue;
42
- }
43
- try {
44
- const msg = JSON.parse(line);
45
- this.handleMessage(msg);
46
- }
47
- catch {
48
- this.emit('error', new Error(`Failed to parse message: ${line}`));
49
- }
50
- }
51
- }
52
- handleMessage(msg) {
53
- if (msg.id !== undefined && (msg.result !== undefined || msg.error !== undefined)) {
54
- const req = this.pendingRequests.get(msg.id);
55
- if (req) {
56
- this.pendingRequests.delete(msg.id);
57
- if (req.timeoutTimer) {
58
- clearTimeout(req.timeoutTimer);
59
- }
60
- if (msg.error !== undefined) {
61
- req.reject(msg.error);
62
- }
63
- else {
64
- req.resolve(msg.result);
65
- }
66
- }
67
- return;
68
- }
69
- if (msg.method !== undefined && msg.id === undefined) {
70
- this.emit('notification', msg.method, msg.params);
71
- if (msg.method === 'events/event') {
72
- this.emit('event', msg.params);
73
- }
74
- }
75
- }
76
- async sendRequest(method, params, timeoutMs = 30_000) {
77
- const id = (0, crypto_1.randomUUID)();
78
- return await new Promise((resolve, reject) => {
79
- const pending = { resolve, reject };
80
- pending.timeoutTimer = setTimeout(() => {
81
- this.pendingRequests.delete(id);
82
- reject(new Error(`request timeout after ${timeoutMs}ms: ${method}`));
83
- }, timeoutMs);
84
- this.pendingRequests.set(id, pending);
85
- const payload = JSON.stringify({
86
- id,
87
- method,
88
- params,
89
- });
90
- this.transport.send(`${payload}\n`);
91
- });
92
- }
93
- sendNotification(method, params) {
94
- const payload = JSON.stringify({
95
- method,
96
- params
97
- });
98
- this.transport.send(`${payload}\n`);
99
- }
100
- async initialize(clientInfo, capabilities) {
101
- const result = await this.sendRequest('initialize', {
102
- protocolVersion: '1.0.0',
103
- clientInfo,
104
- capabilities
105
- });
106
- this.sendNotification('initialized');
107
- this.initialized = true;
108
- return result;
109
- }
110
- async subscribeEvents(families) {
111
- return await this.sendRequest('events/subscribe', { families });
112
- }
113
- }
114
- exports.AppServerClient = AppServerClient;
@@ -1,46 +0,0 @@
1
- import { AppServerClient } from '../../app-server/protocol-client';
2
- import type { CliConfig } from './config';
3
- import { ProgressIndicator } from './progress';
4
- type ClientPreview = {
5
- url: string;
6
- token?: string;
7
- endpoint?: string;
8
- };
9
- export type ServerBootstrapConfig = {
10
- serviceEntry?: string;
11
- license: string;
12
- mp4Path: string;
13
- audioStreamId: number;
14
- videoStreamId: number;
15
- };
16
- export type ClientBootstrapConfig = {
17
- serviceEntry?: string;
18
- peerId: string;
19
- audioStreamId: number;
20
- videoStreamId: number;
21
- consumer: 'web_preview';
22
- };
23
- export declare class BootstrapStepError extends Error {
24
- readonly reasonCode: string;
25
- readonly data: Record<string, unknown>;
26
- constructor(reasonCode: string, message: string, data: Record<string, unknown>);
27
- }
28
- export declare function validateServerConfig(config: CliConfig): ServerBootstrapConfig;
29
- export declare function validateClientConfig(config: CliConfig): ClientBootstrapConfig;
30
- export declare function applyConfiguredServerBootstrap(client: AppServerClient, config: CliConfig, progress?: ProgressIndicator): Promise<{
31
- preparedAssetsDir: string;
32
- mediaSendPolicy: 'AUTO_ON_CONNECTED';
33
- bootstrapSendStreams: Array<Record<string, unknown>>;
34
- }>;
35
- export declare function applyClientStartBootstrap(client: AppServerClient, config: CliConfig, token: string, progress?: ProgressIndicator): Promise<{
36
- connection: unknown;
37
- autoApplied: {
38
- consumer: 'web_preview';
39
- audioStream: unknown;
40
- videoStream: unknown;
41
- audioOutput: unknown;
42
- videoOutput: unknown;
43
- preview: ClientPreview;
44
- };
45
- }>;
46
- export {};