tirtc-devtools-cli 0.1.0 → 0.1.2
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.
- package/README.md +4 -0
- package/USAGE.md +5 -0
- package/dist/cli/src/index.js +11 -2
- package/dist/cli/src/media_assets.d.ts +2 -0
- package/dist/cli/src/media_assets.js +149 -10
- package/dist/cli/src/role_driver.js +8 -3
- package/package.json +1 -1
- package/vendor/devtools/driver/linux-x64/devtools_driver_probe +0 -0
- package/vendor/devtools/driver/macos-arm64/devtools_driver_probe +0 -0
- package/vendor/runtime/linux-x64/include/tirtc/audio.h +21 -0
- package/vendor/runtime/linux-x64/include/tirtc/av.h +28 -0
- package/vendor/runtime/linux-x64/include/tirtc/error.h +41 -2
- package/vendor/runtime/linux-x64/include/tirtc/media_downlink.h +45 -0
- package/vendor/runtime/linux-x64/include/tirtc/video_codec.h +13 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_audio.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_facade.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_foundation_http.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_foundation_logging.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_media.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_transport.a +0 -0
- package/vendor/runtime/linux-x64/lib/libmatrix_runtime_video.a +0 -0
- package/vendor/runtime/linux-x64/manifest.txt +13 -13
- package/vendor/runtime/macos-arm64/include/tirtc/audio.h +21 -0
- package/vendor/runtime/macos-arm64/include/tirtc/av.h +28 -0
- package/vendor/runtime/macos-arm64/include/tirtc/error.h +41 -2
- package/vendor/runtime/macos-arm64/include/tirtc/media_downlink.h +45 -0
- package/vendor/runtime/macos-arm64/include/tirtc/video_codec.h +13 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_audio.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_facade.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_foundation_http.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_foundation_logging.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_media.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_transport.a +0 -0
- package/vendor/runtime/macos-arm64/lib/libmatrix_runtime_video.a +0 -0
- package/vendor/runtime/macos-arm64/manifest.txt +13 -13
- package/vendor/runtime/script/prepare_runtime_media_dataset.sh +32 -0
package/README.md
CHANGED
|
@@ -56,6 +56,10 @@ node products/cli/bin/tirtc-devtools-cli.js --json send start \
|
|
|
56
56
|
--artifact-root .build/devtools-cli/send-movie-h264
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
`send start` 默认持续运行直到用户结束进程;需要自动化限时时再显式传
|
|
60
|
+
`--duration-ms <ms>`。prepared asset 会按完整音视频轨循环,任一轨到达源文件末尾时
|
|
61
|
+
audio/video 同步回到源头并保持 PTS 继续递增。
|
|
62
|
+
|
|
59
63
|
打包入口:
|
|
60
64
|
|
|
61
65
|
```sh
|
package/USAGE.md
CHANGED
|
@@ -110,6 +110,11 @@ node products/cli/bin/tirtc-devtools-cli.js --json send start \
|
|
|
110
110
|
--artifact-root .build/devtools-cli/send-movie-h264
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
By default `send start` keeps running until the process is stopped. Use
|
|
114
|
+
`--duration-ms <ms>` only for bounded automation. Prepared assets loop over the
|
|
115
|
+
full audio/video source cycle; when either track reaches the source end, both
|
|
116
|
+
tracks restart from offset 0 while PTS keeps increasing.
|
|
117
|
+
|
|
113
118
|
The send role writes `bootstrap.json`. That file is a local handoff artifact for
|
|
114
119
|
CLI receive, runtime sample smoke, and validation automation. The token in that
|
|
115
120
|
bootstrap is intended for one receive connection.
|
package/dist/cli/src/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const embedded_paths_1 = require("./embedded_paths");
|
|
10
10
|
const media_assets_1 = require("./media_assets");
|
|
11
|
+
const progress_1 = require("./progress");
|
|
11
12
|
const token_command_1 = require("./token_command");
|
|
12
13
|
const role_driver_1 = require("./role_driver");
|
|
13
14
|
function resolveCliVersion() {
|
|
@@ -69,12 +70,19 @@ function printError(error, options) {
|
|
|
69
70
|
return 1;
|
|
70
71
|
}
|
|
71
72
|
async function runAssetsPrepare(commandOptions, options) {
|
|
73
|
+
const progress = new progress_1.ProgressIndicator();
|
|
74
|
+
progress.start('Preparing media assets');
|
|
72
75
|
try {
|
|
73
76
|
const result = await (0, media_assets_1.prepareMediaAssets)({
|
|
74
77
|
source: commandOptions.source ?? 'runtime/assets/source.mp4',
|
|
75
78
|
outputRoot: commandOptions.outputRoot ?? 'runtime/assets/.workspace',
|
|
76
79
|
overwrite: false,
|
|
80
|
+
}, {
|
|
81
|
+
progress: (message) => {
|
|
82
|
+
progress.update(message);
|
|
83
|
+
},
|
|
77
84
|
});
|
|
85
|
+
progress.succeed(result.cache_hit ? 'Media assets cache hit' : 'Prepared media assets');
|
|
78
86
|
if (options.json) {
|
|
79
87
|
console.log(JSON.stringify({ code: 0, message: 'OK', data: result }));
|
|
80
88
|
}
|
|
@@ -84,6 +92,7 @@ async function runAssetsPrepare(commandOptions, options) {
|
|
|
84
92
|
return 0;
|
|
85
93
|
}
|
|
86
94
|
catch (error) {
|
|
95
|
+
progress.fail('Media assets prepare failed');
|
|
87
96
|
return printError(error, options);
|
|
88
97
|
}
|
|
89
98
|
}
|
|
@@ -117,7 +126,7 @@ send.command('start')
|
|
|
117
126
|
.option('--remote-id <id>', 'server remote id;默认读取 TIRTC_DEVICE_ID')
|
|
118
127
|
.option('--source <path>', 'prepared asset root、manifest_path 或 encoded track;MP4 先运行 assets prepare')
|
|
119
128
|
.option('--video-codec <codec>', 'h264|h265|mjpeg', 'h264')
|
|
120
|
-
.option('--duration-ms <ms>', '
|
|
129
|
+
.option('--duration-ms <ms>', '可选自动结束时长;默认持续运行直到用户结束进程')
|
|
121
130
|
.option('--connect-timeout-ms <ms>', 'service ready / connect 最大等待')
|
|
122
131
|
.option('--first-packet-timeout-ms <ms>', '首包最大等待')
|
|
123
132
|
.option('--bootstrap-token-json <path>', 'script/issue_devtools_token.sh --json 输出文件')
|
|
@@ -143,7 +152,7 @@ receive.command('start')
|
|
|
143
152
|
.option('--video-stream-id <id>', '视频 stream id')
|
|
144
153
|
.option('--consumer <consumer>', 'packet_dump|frame_dump', 'frame_dump')
|
|
145
154
|
.option('--frame-limit <count>', 'frame_dump 帧数上限')
|
|
146
|
-
.option('--duration-ms <ms>', '
|
|
155
|
+
.option('--duration-ms <ms>', '可选自动结束时长;默认由输出条件或用户结束进程')
|
|
147
156
|
.option('--connect-timeout-ms <ms>', 'connect 最大等待')
|
|
148
157
|
.option('--first-packet-timeout-ms <ms>', '首包最大等待')
|
|
149
158
|
.option('--first-output-timeout-ms <ms>', '首帧输出最大等待')
|
|
@@ -17,9 +17,11 @@ type ExecFileLike = (file: string, args: string[], options: {
|
|
|
17
17
|
stdout?: string | Buffer;
|
|
18
18
|
stderr?: string | Buffer;
|
|
19
19
|
}>;
|
|
20
|
+
type ProgressCallback = (message: string) => void;
|
|
20
21
|
type PrepareMediaAssetsOptions = {
|
|
21
22
|
repoRoot?: string;
|
|
22
23
|
execFile?: ExecFileLike;
|
|
24
|
+
progress?: ProgressCallback;
|
|
23
25
|
};
|
|
24
26
|
export declare function prepareMediaAssets(request: PrepareMediaAssetsRequest, options?: PrepareMediaAssetsOptions): Promise<PrepareMediaAssetsResult>;
|
|
25
27
|
export {};
|
|
@@ -10,6 +10,17 @@ const path_1 = __importDefault(require("path"));
|
|
|
10
10
|
const util_1 = require("util");
|
|
11
11
|
const embedded_paths_1 = require("./embedded_paths");
|
|
12
12
|
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
13
|
+
class PrepareMediaAssetsError extends Error {
|
|
14
|
+
reasonCode;
|
|
15
|
+
constructor(message, reasonCode) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = 'PrepareMediaAssetsError';
|
|
18
|
+
this.reasonCode = reasonCode;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const prepareProgressPrefix = '[prepare_runtime_media_dataset] progress: ';
|
|
22
|
+
const prepareErrorPrefix = '[prepare_runtime_media_dataset] error: ';
|
|
23
|
+
const prepareExecMaxBuffer = 10 * 1024 * 1024;
|
|
13
24
|
function resolveRepoRoot(fromDir) {
|
|
14
25
|
const candidates = [
|
|
15
26
|
path_1.default.resolve(fromDir, '../../..'),
|
|
@@ -36,23 +47,72 @@ function resolvePrepareScript(repoRoot) {
|
|
|
36
47
|
}
|
|
37
48
|
return path_1.default.join(repoRoot, 'runtime/script/prepare_runtime_media_dataset.sh');
|
|
38
49
|
}
|
|
39
|
-
function
|
|
50
|
+
function appendBounded(chunks, text, currentSize, maxSize) {
|
|
51
|
+
const nextSize = currentSize + Buffer.byteLength(text);
|
|
52
|
+
if (nextSize > maxSize) {
|
|
53
|
+
throw new Error('media assets prepare output exceeded buffer limit');
|
|
54
|
+
}
|
|
55
|
+
chunks.push(text);
|
|
56
|
+
return nextSize;
|
|
57
|
+
}
|
|
58
|
+
function emitProgressLine(line, progress) {
|
|
59
|
+
if (!progress || !line.startsWith(prepareProgressPrefix)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const message = line.slice(prepareProgressPrefix.length).trim();
|
|
63
|
+
if (message.length > 0) {
|
|
64
|
+
progress(message);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function emitBufferedProgress(stderr, progress) {
|
|
68
|
+
if (!stderr || !progress) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
String(stderr)
|
|
72
|
+
.split(/\r?\n/)
|
|
73
|
+
.forEach((line) => {
|
|
74
|
+
emitProgressLine(line, progress);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function stripProgressLines(message) {
|
|
78
|
+
const lines = message.split(/\r?\n/);
|
|
79
|
+
const nonProgressLines = lines.filter((line) => !line.startsWith(prepareProgressPrefix));
|
|
80
|
+
const cleaned = nonProgressLines.join('\n').trim();
|
|
81
|
+
return cleaned.length > 0 ? cleaned : message.trim();
|
|
82
|
+
}
|
|
83
|
+
function normalizeExecErrorMessage(message) {
|
|
84
|
+
const cleaned = stripProgressLines(message);
|
|
85
|
+
const errorLine = cleaned.split(/\r?\n/).find((line) => line.startsWith(prepareErrorPrefix));
|
|
86
|
+
const normalized = errorLine ? errorLine.slice(prepareErrorPrefix.length).trim() : cleaned;
|
|
87
|
+
const reasonMatch = normalized.match(/^([a-z][a-z0-9_]*):\s*(.+)$/);
|
|
88
|
+
if (reasonMatch) {
|
|
89
|
+
return {
|
|
90
|
+
reasonCode: reasonMatch[1],
|
|
91
|
+
message: reasonMatch[2],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return { message: normalized };
|
|
95
|
+
}
|
|
96
|
+
function parseExecError(error, progress) {
|
|
40
97
|
if (!error || typeof error !== 'object') {
|
|
41
|
-
return String(error);
|
|
98
|
+
return normalizeExecErrorMessage(String(error));
|
|
42
99
|
}
|
|
43
100
|
const typed = error;
|
|
101
|
+
if (!typed.progressEmitted) {
|
|
102
|
+
emitBufferedProgress(typed.stderr, progress);
|
|
103
|
+
}
|
|
44
104
|
const stderr = typeof typed.stderr === 'string' ? typed.stderr.trim() : typed.stderr?.toString('utf8').trim();
|
|
45
105
|
if (stderr && stderr.length > 0) {
|
|
46
|
-
return stderr;
|
|
106
|
+
return normalizeExecErrorMessage(stderr);
|
|
47
107
|
}
|
|
48
108
|
const stdout = typeof typed.stdout === 'string' ? typed.stdout.trim() : typed.stdout?.toString('utf8').trim();
|
|
49
109
|
if (stdout && stdout.length > 0) {
|
|
50
|
-
return stdout;
|
|
110
|
+
return normalizeExecErrorMessage(stdout);
|
|
51
111
|
}
|
|
52
112
|
if (typed.message && typed.message.length > 0) {
|
|
53
|
-
return typed.message;
|
|
113
|
+
return normalizeExecErrorMessage(typed.message);
|
|
54
114
|
}
|
|
55
|
-
return 'process failed';
|
|
115
|
+
return { message: 'process failed' };
|
|
56
116
|
}
|
|
57
117
|
function assertPrepareRequest(request) {
|
|
58
118
|
if (!request.source || request.source.trim().length === 0) {
|
|
@@ -65,6 +125,74 @@ function assertPrepareRequest(request) {
|
|
|
65
125
|
throw new Error('media assets prepare requires non-empty --output-dir when provided');
|
|
66
126
|
}
|
|
67
127
|
}
|
|
128
|
+
function execPrepareWithProgress(file, args, options) {
|
|
129
|
+
return new Promise((resolve, reject) => {
|
|
130
|
+
const child = (0, child_process_1.spawn)(file, args, {
|
|
131
|
+
cwd: options.cwd,
|
|
132
|
+
env: options.env,
|
|
133
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
134
|
+
});
|
|
135
|
+
const stdoutChunks = [];
|
|
136
|
+
const stderrChunks = [];
|
|
137
|
+
let stdoutSize = 0;
|
|
138
|
+
let stderrSize = 0;
|
|
139
|
+
let stderrLineBuffer = '';
|
|
140
|
+
let settled = false;
|
|
141
|
+
function rejectOnce(error) {
|
|
142
|
+
if (settled) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
settled = true;
|
|
146
|
+
child.kill();
|
|
147
|
+
reject(error);
|
|
148
|
+
}
|
|
149
|
+
child.stdout.on('data', (chunk) => {
|
|
150
|
+
try {
|
|
151
|
+
stdoutSize = appendBounded(stdoutChunks, chunk.toString('utf8'), stdoutSize, options.maxBuffer);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
rejectOnce(error instanceof Error ? error : new Error(String(error)));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
child.stderr.on('data', (chunk) => {
|
|
158
|
+
const text = chunk.toString('utf8');
|
|
159
|
+
try {
|
|
160
|
+
stderrSize = appendBounded(stderrChunks, text, stderrSize, options.maxBuffer);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
rejectOnce(error instanceof Error ? error : new Error(String(error)));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
stderrLineBuffer += text;
|
|
167
|
+
const lines = stderrLineBuffer.split(/\r?\n/);
|
|
168
|
+
stderrLineBuffer = lines.pop() ?? '';
|
|
169
|
+
lines.forEach((line) => {
|
|
170
|
+
emitProgressLine(line, options.progress);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
child.on('error', (error) => {
|
|
174
|
+
rejectOnce(error);
|
|
175
|
+
});
|
|
176
|
+
child.on('close', (code, signal) => {
|
|
177
|
+
if (settled) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
settled = true;
|
|
181
|
+
if (stderrLineBuffer.length > 0) {
|
|
182
|
+
emitProgressLine(stderrLineBuffer, options.progress);
|
|
183
|
+
}
|
|
184
|
+
const stdout = stdoutChunks.join('');
|
|
185
|
+
const stderr = stderrChunks.join('');
|
|
186
|
+
if (code === 0) {
|
|
187
|
+
resolve({ stdout, stderr });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const error = new Error(signal ? `process killed by signal ${signal}` : `process exited with code ${code}`);
|
|
191
|
+
Object.assign(error, { stdout, stderr, progressEmitted: true });
|
|
192
|
+
reject(error);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
68
196
|
async function prepareMediaAssets(request, options = {}) {
|
|
69
197
|
assertPrepareRequest(request);
|
|
70
198
|
const repoRoot = options.repoRoot ? path_1.default.resolve(options.repoRoot) : resolveDefaultRepoRoot();
|
|
@@ -88,18 +216,29 @@ async function prepareMediaAssets(request, options = {}) {
|
|
|
88
216
|
}
|
|
89
217
|
let stdout = '';
|
|
90
218
|
try {
|
|
91
|
-
const
|
|
219
|
+
const execOptions = {
|
|
92
220
|
cwd: repoRoot,
|
|
93
221
|
env: {
|
|
94
222
|
...process.env,
|
|
95
223
|
TIRTC_ENSURE_FFMPEG_SCRIPT: ensureFfmpegScriptPath,
|
|
96
224
|
},
|
|
97
|
-
maxBuffer:
|
|
98
|
-
}
|
|
225
|
+
maxBuffer: prepareExecMaxBuffer,
|
|
226
|
+
};
|
|
227
|
+
const useStreamingProgress = options.progress && !options.execFile;
|
|
228
|
+
const result = useStreamingProgress
|
|
229
|
+
? await execPrepareWithProgress('bash', [scriptPath, ...args], {
|
|
230
|
+
...execOptions,
|
|
231
|
+
progress: options.progress,
|
|
232
|
+
})
|
|
233
|
+
: await execFile('bash', [scriptPath, ...args], execOptions);
|
|
234
|
+
if (!useStreamingProgress) {
|
|
235
|
+
emitBufferedProgress(result.stderr, options.progress);
|
|
236
|
+
}
|
|
99
237
|
stdout = String(result.stdout ?? '').trim();
|
|
100
238
|
}
|
|
101
239
|
catch (error) {
|
|
102
|
-
|
|
240
|
+
const parsed = parseExecError(error, options.progress);
|
|
241
|
+
throw new PrepareMediaAssetsError(parsed.message, parsed.reasonCode);
|
|
103
242
|
}
|
|
104
243
|
let parsed;
|
|
105
244
|
try {
|
|
@@ -14,7 +14,6 @@ const embedded_paths_1 = require("./embedded_paths");
|
|
|
14
14
|
const token_tool_1 = require("./token_tool");
|
|
15
15
|
const defaultAudioStreamId = 10;
|
|
16
16
|
const defaultVideoStreamId = 11;
|
|
17
|
-
const defaultDurationMs = 10000;
|
|
18
17
|
const defaultConnectTimeoutMs = 10000;
|
|
19
18
|
const defaultFirstPacketTimeoutMs = 10000;
|
|
20
19
|
const defaultFirstOutputTimeoutMs = 12000;
|
|
@@ -137,6 +136,12 @@ function parsePositiveInt(raw, fallback, name) {
|
|
|
137
136
|
}
|
|
138
137
|
return parsed;
|
|
139
138
|
}
|
|
139
|
+
function parseOptionalPositiveInt(raw, name) {
|
|
140
|
+
if (raw === undefined) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
return parsePositiveInt(raw, 1, name);
|
|
144
|
+
}
|
|
140
145
|
function requireEnv(name) {
|
|
141
146
|
const value = process.env[name]?.trim();
|
|
142
147
|
if (!value) {
|
|
@@ -338,7 +343,7 @@ async function buildSendRequest(roots, artifactRoot, options) {
|
|
|
338
343
|
},
|
|
339
344
|
output: { consumer: 'frame_dump', video: { frame_limit: defaultFrameLimit } },
|
|
340
345
|
run: {
|
|
341
|
-
duration_ms:
|
|
346
|
+
duration_ms: parseOptionalPositiveInt(options.durationMs, '--duration-ms'),
|
|
342
347
|
connect_timeout_ms: parsePositiveInt(options.connectTimeoutMs, defaultConnectTimeoutMs, '--connect-timeout-ms'),
|
|
343
348
|
first_packet_timeout_ms: parsePositiveInt(options.firstPacketTimeoutMs, defaultFirstPacketTimeoutMs, '--first-packet-timeout-ms'),
|
|
344
349
|
first_output_timeout_ms: defaultFirstOutputTimeoutMs,
|
|
@@ -386,7 +391,7 @@ function buildReceiveRequest(roots, artifactRoot, options) {
|
|
|
386
391
|
video: { frame_limit: parsePositiveInt(options.frameLimit, defaultFrameLimit, '--frame-limit') },
|
|
387
392
|
},
|
|
388
393
|
run: {
|
|
389
|
-
duration_ms:
|
|
394
|
+
duration_ms: parseOptionalPositiveInt(options.durationMs, '--duration-ms'),
|
|
390
395
|
connect_timeout_ms: parsePositiveInt(options.connectTimeoutMs, defaultConnectTimeoutMs, '--connect-timeout-ms'),
|
|
391
396
|
first_packet_timeout_ms: parsePositiveInt(options.firstPacketTimeoutMs, defaultFirstPacketTimeoutMs, '--first-packet-timeout-ms'),
|
|
392
397
|
first_output_timeout_ms: parsePositiveInt(options.firstOutputTimeoutMs, defaultFirstOutputTimeoutMs, '--first-output-timeout-ms'),
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -96,6 +96,17 @@ typedef struct TirtcAudioOutputMetricsSnapshot {
|
|
|
96
96
|
TirtcPendingDurationMetrics pending;
|
|
97
97
|
} TirtcAudioOutputMetricsSnapshot;
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Diagnostic facts currently known for an audio output.
|
|
101
|
+
*
|
|
102
|
+
* The snapshot is a caller-owned value copy. Zero-initialized fields mean the output has not yet
|
|
103
|
+
* observed a matching runtime fact or only cached zero-state is available. This diagnostic API is
|
|
104
|
+
* intended for UI/debug visibility and logs, not for playback control decisions.
|
|
105
|
+
*/
|
|
106
|
+
typedef struct TirtcAudioOutputDebugSnapshot {
|
|
107
|
+
TirtcMediaCodec codec;
|
|
108
|
+
} TirtcAudioOutputDebugSnapshot;
|
|
109
|
+
|
|
99
110
|
/**
|
|
100
111
|
* Audio input observer.
|
|
101
112
|
*
|
|
@@ -209,6 +220,16 @@ TirtcError tirtc_audio_output_stop_raw_dump(TirtcAudioOutput* output);
|
|
|
209
220
|
TirtcError tirtc_metrics_audio_output_get_snapshot(TirtcAudioOutput* output,
|
|
210
221
|
TirtcAudioOutputMetricsSnapshot* out_snapshot);
|
|
211
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Copies the current or cached audio output diagnostic snapshot.
|
|
225
|
+
*
|
|
226
|
+
* The output owns the underlying media downlink. Callers provide only `out_snapshot` storage and do
|
|
227
|
+
* not receive ownership of any runtime object. The function returns `TIRTC_ERROR_INVALID_ARGUMENT`
|
|
228
|
+
* for null arguments and does not emit output callbacks or change output state.
|
|
229
|
+
*/
|
|
230
|
+
TirtcError tirtc_audio_output_get_debug_snapshot(TirtcAudioOutput* output,
|
|
231
|
+
TirtcAudioOutputDebugSnapshot* out_snapshot);
|
|
232
|
+
|
|
212
233
|
#ifdef __cplusplus
|
|
213
234
|
}
|
|
214
235
|
#endif
|
|
@@ -48,6 +48,23 @@ typedef struct TirtcVideoOutputMetricsSnapshot {
|
|
|
48
48
|
TirtcPendingDurationMetrics pending;
|
|
49
49
|
} TirtcVideoOutputMetricsSnapshot;
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Diagnostic facts currently known for a video output.
|
|
53
|
+
*
|
|
54
|
+
* The snapshot is a caller-owned value copy. `resolved_decoder_backend` is the runtime route that
|
|
55
|
+
* has actually locked, so AUTO fallback reports the concrete backend family instead of the request.
|
|
56
|
+
* Zero values mean no current fact or only cached zero-state is available. Additive changes require
|
|
57
|
+
* a new V2 struct/function instead of extending this layout.
|
|
58
|
+
*/
|
|
59
|
+
typedef struct TirtcVideoOutputDebugSnapshot {
|
|
60
|
+
TirtcMediaCodec codec;
|
|
61
|
+
TirtcVideoBitstreamFormat bitstream_format;
|
|
62
|
+
uint32_t width;
|
|
63
|
+
uint32_t height;
|
|
64
|
+
TirtcVideoDecoderPreference requested_decoder_preference;
|
|
65
|
+
TirtcVideoDecoderBackendKind resolved_decoder_backend;
|
|
66
|
+
} TirtcVideoOutputDebugSnapshot;
|
|
67
|
+
|
|
51
68
|
typedef struct TirtcVideoOutputOptions {
|
|
52
69
|
TirtcVideoDecoderPreference decoder_preference;
|
|
53
70
|
} TirtcVideoOutputOptions;
|
|
@@ -201,6 +218,17 @@ TirtcError tirtc_video_output_stop_raw_dump(TirtcVideoOutput* output);
|
|
|
201
218
|
TirtcError tirtc_metrics_video_output_get_snapshot(TirtcVideoOutput* output,
|
|
202
219
|
TirtcVideoOutputMetricsSnapshot* out_snapshot);
|
|
203
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Copies the current or cached video output diagnostic snapshot.
|
|
223
|
+
*
|
|
224
|
+
* The output owns the underlying media downlink and the returned data is only a value copy. Use
|
|
225
|
+
* this for diagnostics and UI visibility, not to drive decoder selection. The function returns
|
|
226
|
+
* `TIRTC_ERROR_INVALID_ARGUMENT` for null arguments and does not emit output callbacks or change
|
|
227
|
+
* output state.
|
|
228
|
+
*/
|
|
229
|
+
TirtcError tirtc_video_output_get_debug_snapshot(TirtcVideoOutput* output,
|
|
230
|
+
TirtcVideoOutputDebugSnapshot* out_snapshot);
|
|
231
|
+
|
|
204
232
|
#ifdef __cplusplus
|
|
205
233
|
}
|
|
206
234
|
#endif
|
|
@@ -9,8 +9,6 @@ typedef enum TirtcError {
|
|
|
9
9
|
TIRTC_ERROR_OK = 0,
|
|
10
10
|
TIRTC_ERROR_INVALID_ARGUMENT = 6000,
|
|
11
11
|
TIRTC_ERROR_NOT_INITIALIZED = 6001,
|
|
12
|
-
TIRTC_ERROR_INTERNAL = 6002,
|
|
13
|
-
TIRTC_ERROR_NOT_READY = 6003,
|
|
14
12
|
TIRTC_ERROR_UNSUPPORTED_LOOP_POLICY = 6004,
|
|
15
13
|
TIRTC_ERROR_SOURCE_HASH_MISMATCH = 6005,
|
|
16
14
|
TIRTC_ERROR_ALREADY_STOPPED = 6006,
|
|
@@ -52,6 +50,47 @@ typedef enum TirtcError {
|
|
|
52
50
|
TIRTC_ERROR_VIDEO_DECODER_RUNTIME_FAILED = 6040,
|
|
53
51
|
TIRTC_ERROR_VIDEO_OUTPUT_TARGET_UNAVAILABLE = 6041,
|
|
54
52
|
TIRTC_ERROR_VIDEO_OUTPUT_RENDER_FAILED = 6042,
|
|
53
|
+
TIRTC_ERROR_RESOURCE_EXHAUSTED = 6043,
|
|
54
|
+
TIRTC_ERROR_FILE_OPEN_FAILED = 6044,
|
|
55
|
+
TIRTC_ERROR_FILE_READ_FAILED = 6045,
|
|
56
|
+
TIRTC_ERROR_FILE_WRITE_FAILED = 6046,
|
|
57
|
+
TIRTC_ERROR_HTTP_REQUEST_FAILED = 6047,
|
|
58
|
+
TIRTC_ERROR_LOG_EXPORT_FAILED = 6048,
|
|
59
|
+
TIRTC_ERROR_LOG_UPLOAD_FAILED = 6049,
|
|
60
|
+
TIRTC_ERROR_S3_UPLOAD_FAILED = 6050,
|
|
61
|
+
TIRTC_ERROR_AUDIO_INPUT_OPEN_FAILED = 6051,
|
|
62
|
+
TIRTC_ERROR_AUDIO_INPUT_RUNTIME_FAILED = 6052,
|
|
63
|
+
TIRTC_ERROR_AUDIO_OUTPUT_OPEN_FAILED = 6053,
|
|
64
|
+
TIRTC_ERROR_AUDIO_OUTPUT_RUNTIME_FAILED = 6054,
|
|
65
|
+
TIRTC_ERROR_AUDIO_PROCESSING_INITIALIZATION_FAILED = 6055,
|
|
66
|
+
TIRTC_ERROR_AUDIO_PROCESSING_RUNTIME_FAILED = 6056,
|
|
67
|
+
TIRTC_ERROR_VIDEO_ENCODER_RUNTIME_FAILED = 6057,
|
|
68
|
+
TIRTC_ERROR_VIDEO_PROCESSING_RUNTIME_FAILED = 6058,
|
|
69
|
+
TIRTC_ERROR_VIDEO_INPUT_OPEN_FAILED = 6059,
|
|
70
|
+
TIRTC_ERROR_VIDEO_INPUT_RUNTIME_FAILED = 6060,
|
|
71
|
+
TIRTC_ERROR_VIDEO_OUTPUT_OPEN_FAILED = 6061,
|
|
72
|
+
TIRTC_ERROR_MEDIA_UPLINK_CREATE_FAILED = 6062,
|
|
73
|
+
TIRTC_ERROR_MEDIA_UPLINK_START_FAILED = 6063,
|
|
74
|
+
TIRTC_ERROR_MEDIA_DOWNLINK_DECODE_FAILED = 6064,
|
|
75
|
+
TIRTC_ERROR_MEDIA_RAW_DUMP_FAILED = 6065,
|
|
76
|
+
TIRTC_ERROR_FACADE_RUNTIME_FAILED = 6066,
|
|
77
|
+
TIRTC_ERROR_LOG_WRITE_FAILED = 6067,
|
|
78
|
+
TIRTC_ERROR_AUDIO_ENCODER_RUNTIME_FAILED = 6068,
|
|
79
|
+
TIRTC_ERROR_AUDIO_DECODER_RUNTIME_FAILED = 6069,
|
|
80
|
+
TIRTC_ERROR_HTTP_CLIENT_UNAVAILABLE = 6070,
|
|
81
|
+
TIRTC_ERROR_HTTP_TLS_UNSUPPORTED = 6071,
|
|
82
|
+
TIRTC_ERROR_UPLOAD_TOKEN_EXPIRED = 6072,
|
|
83
|
+
TIRTC_ERROR_STREAM_ID_IN_USE = 6073,
|
|
84
|
+
TIRTC_ERROR_VIDEO_PREVIEW_IN_USE = 6074,
|
|
85
|
+
TIRTC_ERROR_FACADE_PEER_ID_UNAVAILABLE = 6075,
|
|
86
|
+
TIRTC_ERROR_MEDIA_DOWNLINK_QUEUE_FULL = 6076,
|
|
87
|
+
TIRTC_ERROR_MEDIA_DOWNLINK_OUTPUT_PENDING = 6077,
|
|
88
|
+
TIRTC_ERROR_TRANSPORT_INVALID_HANDLE = 6078,
|
|
89
|
+
TIRTC_ERROR_VIDEO_ENCODER_INPUT_PENDING = 6079,
|
|
90
|
+
TIRTC_ERROR_VIDEO_ENCODER_OUTPUT_PENDING = 6080,
|
|
91
|
+
TIRTC_ERROR_VIDEO_DECODER_INPUT_PENDING = 6081,
|
|
92
|
+
TIRTC_ERROR_VIDEO_DECODER_OUTPUT_PENDING = 6082,
|
|
93
|
+
TIRTC_ERROR_MEDIA_UPLINK_INPUT_MODE_MISMATCH = 6083,
|
|
55
94
|
} TirtcError;
|
|
56
95
|
|
|
57
96
|
const char* tirtc_error_to_string(TirtcError error);
|
|
@@ -86,6 +86,33 @@ typedef struct TirtcMediaDownlinkVideoMetricsSnapshot {
|
|
|
86
86
|
TirtcMediaDownlinkPendingMetricsSnapshot pending;
|
|
87
87
|
} TirtcMediaDownlinkVideoMetricsSnapshot;
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Diagnostic facts currently known by an audio downlink.
|
|
91
|
+
*
|
|
92
|
+
* The snapshot is a value copy into caller-owned storage. `codec` is
|
|
93
|
+
* `TIRTC_MEDIA_CODEC_NONE` until the downlink accepts a valid encoded audio frame.
|
|
94
|
+
*/
|
|
95
|
+
typedef struct TirtcMediaDownlinkAudioDebugSnapshot {
|
|
96
|
+
TirtcMediaCodec codec;
|
|
97
|
+
} TirtcMediaDownlinkAudioDebugSnapshot;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Diagnostic facts currently known by a video downlink.
|
|
101
|
+
*
|
|
102
|
+
* The snapshot is a value copy into caller-owned storage. Zero values mean the downlink has not
|
|
103
|
+
* observed the corresponding fact since start/reset. `requested_decoder_preference` reflects the
|
|
104
|
+
* configured option; `resolved_decoder_backend` is only set after the runtime locks a concrete
|
|
105
|
+
* decode route.
|
|
106
|
+
*/
|
|
107
|
+
typedef struct TirtcMediaDownlinkVideoDebugSnapshot {
|
|
108
|
+
TirtcMediaCodec codec;
|
|
109
|
+
TirtcVideoBitstreamFormat bitstream_format;
|
|
110
|
+
uint32_t width;
|
|
111
|
+
uint32_t height;
|
|
112
|
+
TirtcVideoDecoderPreference requested_decoder_preference;
|
|
113
|
+
TirtcVideoDecoderBackendKind resolved_decoder_backend;
|
|
114
|
+
} TirtcMediaDownlinkVideoDebugSnapshot;
|
|
115
|
+
|
|
89
116
|
TirtcError tirtc_media_downlink_audio_create(TirtcMediaDownlinkAudio** out_downlink);
|
|
90
117
|
void tirtc_media_downlink_audio_retain(TirtcMediaDownlinkAudio* downlink);
|
|
91
118
|
void tirtc_media_downlink_audio_release(TirtcMediaDownlinkAudio* downlink);
|
|
@@ -147,6 +174,24 @@ TirtcError tirtc_media_downlink_video_get_metrics_snapshot(
|
|
|
147
174
|
TirtcMediaDownlinkVideo* downlink, TirtcMediaDownlinkVideoMetricsSnapshot* out_snapshot);
|
|
148
175
|
void tirtc_media_downlink_video_reset_metrics_session(TirtcMediaDownlinkVideo* downlink);
|
|
149
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Copies the current audio downlink diagnostic snapshot.
|
|
179
|
+
*
|
|
180
|
+
* This call does not start, stop, flush, or otherwise change the downlink. It returns
|
|
181
|
+
* `TIRTC_ERROR_INVALID_ARGUMENT` when `downlink` or `out_snapshot` is null.
|
|
182
|
+
*/
|
|
183
|
+
TirtcError tirtc_media_downlink_audio_get_debug_snapshot(
|
|
184
|
+
TirtcMediaDownlinkAudio* downlink, TirtcMediaDownlinkAudioDebugSnapshot* out_snapshot);
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Copies the current video downlink diagnostic snapshot.
|
|
188
|
+
*
|
|
189
|
+
* This call does not start, stop, flush, or otherwise change the downlink. It returns
|
|
190
|
+
* `TIRTC_ERROR_INVALID_ARGUMENT` when `downlink` or `out_snapshot` is null.
|
|
191
|
+
*/
|
|
192
|
+
TirtcError tirtc_media_downlink_video_get_debug_snapshot(
|
|
193
|
+
TirtcMediaDownlinkVideo* downlink, TirtcMediaDownlinkVideoDebugSnapshot* out_snapshot);
|
|
194
|
+
|
|
150
195
|
#ifdef __cplusplus
|
|
151
196
|
}
|
|
152
197
|
#endif
|
|
@@ -26,6 +26,19 @@ typedef enum TirtcVideoDecoderPreference {
|
|
|
26
26
|
TIRTC_VIDEO_DECODER_PREFERENCE_HARDWARE = 2,
|
|
27
27
|
} TirtcVideoDecoderPreference;
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Backend family that is actually handling a video decoder route.
|
|
31
|
+
*
|
|
32
|
+
* `UNKNOWN` means the runtime has not locked a decoder route or the current snapshot cannot prove
|
|
33
|
+
* one. The enum intentionally reports only the supported backend family; platform-specific decoder
|
|
34
|
+
* names and native handles are not part of this public surface.
|
|
35
|
+
*/
|
|
36
|
+
typedef enum TirtcVideoDecoderBackendKind {
|
|
37
|
+
TIRTC_VIDEO_DECODER_BACKEND_KIND_UNKNOWN = 0,
|
|
38
|
+
TIRTC_VIDEO_DECODER_BACKEND_KIND_SOFTWARE = 1,
|
|
39
|
+
TIRTC_VIDEO_DECODER_BACKEND_KIND_HARDWARE = 2,
|
|
40
|
+
} TirtcVideoDecoderBackendKind;
|
|
41
|
+
|
|
29
42
|
typedef enum TirtcVideoEncoderBackendKind {
|
|
30
43
|
TIRTC_VIDEO_ENCODER_BACKEND_KIND_SOFTWARE = 1,
|
|
31
44
|
TIRTC_VIDEO_ENCODER_BACKEND_KIND_HARDWARE = 2,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
platform=linux-x64
|
|
2
2
|
profile=full
|
|
3
|
-
staged_at_utc=2026-04-
|
|
3
|
+
staged_at_utc=2026-04-30T09:51:52Z
|
|
4
4
|
source_sdk=/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.build/sdk/linux-x64
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
bfc096be1484ac2b1c2776ccabfa2a4c6a982e869abf875192ff06fad85e82ca include/tirtc/audio.h
|
|
7
7
|
6d972ccfe150a3b4f2d7f18fa92b3ade9210c1c8bb754d061ac6b7997b59e2cb include/tirtc/audio_codec.h
|
|
8
8
|
7bacbdb2d8bb10d6444036a8fef42f2a8e3ea34dfc38e165ee678d61f189db41 include/tirtc/audio_frame.h
|
|
9
9
|
fb8ea35263167c33487bd3aa503c26ed2dfbf97877f7bda92c10065cd5c97c13 include/tirtc/audio_io.h
|
|
@@ -13,17 +13,17 @@ c2e1f31dcc75be461c577d18b1cebe32774f212d51cb4dd2a5b5a9bfe62b693e include/tirtc/
|
|
|
13
13
|
51cbc911fe9f9834046f0e0a1a7cdd814a8e194a615894a8b4d11f9e5f095610 include/tirtc/audio_io_windows.h
|
|
14
14
|
21f60729117260a44af22c1af986ef17d22673b102b7b7a035f492d0665cce16 include/tirtc/audio_processing.h
|
|
15
15
|
0ca7c3c630b1242f51a0fd8154097c0a332b4c816a5707090e4381719852998c include/tirtc/audio_sample_rate.h
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
58807ba56770f38f47aec995661cadf9d3c1d6ea7bfc940767f1ce67317c7546 include/tirtc/av.h
|
|
17
|
+
0f3e2f454c35e8c2f79bdc93ed77f9f1622751e5a05defa8c9d4213ed8a797c5 include/tirtc/error.h
|
|
18
18
|
ae805545a9515edc9b94262e72ad2c7b7d649288166f4daeb450d8a55e82ae0b include/tirtc/foundation/build_info.h
|
|
19
19
|
7cf8b372a3d48d4de4a65a04c7f102281a7b42cebb9ec247853d3c53afb63b6a include/tirtc/http.h
|
|
20
20
|
70bbf93b84d9d1a85f376d9986de570c1f658319e1e5ab6d621f7a4d41033f5c include/tirtc/logging.h
|
|
21
21
|
7e2f7f81afe37e22f5414d9db32438edd948ff775230c3a0a17ff9ac1a0b560e include/tirtc/media_codec.h
|
|
22
|
-
|
|
22
|
+
ca63fe4fa0c787f20923e264e116fa6d7cb8194a227c03be4e9843d0ce5a9864 include/tirtc/media_downlink.h
|
|
23
23
|
e64191a39004165cdcd11b2ca824af34d4bfe02f7ec3c3101fa9291f56488c30 include/tirtc/media_uplink.h
|
|
24
24
|
489f6c9caa3e4094566b660ef0a002a39c66c1956ef0a1bdb6eacca3798c849a include/tirtc/transport.h
|
|
25
25
|
bb9c1bf46f2ab51a9f7adb211276c8563b09e7968031c0c6abeebc0eddd66acb include/tirtc/trp.h
|
|
26
|
-
|
|
26
|
+
92b3db6e2cb02265ad5db01881edce9d4e095b1dadf449dce5d8bb5362957e33 include/tirtc/video_codec.h
|
|
27
27
|
e51379666c199588cc33279ccf52248035d1cae3d1d468b1615ebf29f0b39c9c include/tirtc/video_frame.h
|
|
28
28
|
2a02645d82c58d433c7306a9f0bcd31d0f3e560b63822f7e80919761b81a6284 include/tirtc/video_io.h
|
|
29
29
|
9930dce5e8e2b12a1ab28ee91f3fb46f6cf3487e515ea2b4ec0e00009bd5f070 include/tirtc/video_io_android.h
|
|
@@ -33,13 +33,13 @@ cae0bbeb884e5466a56da15182c78cc22baab6c743f349a58d3595f623333585 include/tirtc/
|
|
|
33
33
|
8cd6b66bea14890a665cc317f8572429b2c3e4463773f8b77c1e4dc30a4a8747 include/tirtc/video_processing.h
|
|
34
34
|
ceb7cdd45efae57e5bd53d4177cb20c4a0cb9917fcdd23127b050d69c8b919ac lib/libTiRTC.a
|
|
35
35
|
b1f4135025cb8e8520a14268d831b9998920a4239f84bb6b409d0e4909fd5bee lib/libcrypto.a
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
8e3aff3a400fe0971c61511947c0e69d06754002d970e21eaab2339ae38b4a42 lib/libmatrix_runtime_audio.a
|
|
37
|
+
09696896a45a4fab199f0767979471c947b252fc8741a0e803624cdac6953b59 lib/libmatrix_runtime_facade.a
|
|
38
|
+
2c8cc881eeeae679129360df5813dec17d0e33935f196d79cf79671dbd0c8581 lib/libmatrix_runtime_foundation_http.a
|
|
39
|
+
4623c3c72a263f0397e554435e4998551c274b5b40f98f331902a8c0c8a29e3e lib/libmatrix_runtime_foundation_logging.a
|
|
40
|
+
fe6b5575ce5e80f81e07a7799a05d0a8ee5a338915a28ada86d9009eee952e96 lib/libmatrix_runtime_media.a
|
|
41
|
+
86d9b41f84c6bcc13f8d23a1f9b46d97fe6769573758722f9f6c8d4a130306be lib/libmatrix_runtime_transport.a
|
|
42
|
+
6ac178f5cd371e9a5be1989dd1e8a3767291f4c4d9d30dcf12ecdd75a2081afa lib/libmatrix_runtime_video.a
|
|
43
43
|
511d521f7972df3993e5976d6e2dbcad7a6fbce9be15071274d0cbd9d51157f5 lib/libssl.a
|
|
44
44
|
a67ec9034848ef24a1b17671e444daa62a8f9e6b8319a1e932593908720ff2a1 lib/libwebrtc_apm.a
|
|
45
45
|
700e455255897e3cffab13ca593a6e4d9d11383ae609215cbbd6043a63d47161 lib/libxlog.a
|
|
@@ -96,6 +96,17 @@ typedef struct TirtcAudioOutputMetricsSnapshot {
|
|
|
96
96
|
TirtcPendingDurationMetrics pending;
|
|
97
97
|
} TirtcAudioOutputMetricsSnapshot;
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Diagnostic facts currently known for an audio output.
|
|
101
|
+
*
|
|
102
|
+
* The snapshot is a caller-owned value copy. Zero-initialized fields mean the output has not yet
|
|
103
|
+
* observed a matching runtime fact or only cached zero-state is available. This diagnostic API is
|
|
104
|
+
* intended for UI/debug visibility and logs, not for playback control decisions.
|
|
105
|
+
*/
|
|
106
|
+
typedef struct TirtcAudioOutputDebugSnapshot {
|
|
107
|
+
TirtcMediaCodec codec;
|
|
108
|
+
} TirtcAudioOutputDebugSnapshot;
|
|
109
|
+
|
|
99
110
|
/**
|
|
100
111
|
* Audio input observer.
|
|
101
112
|
*
|
|
@@ -209,6 +220,16 @@ TirtcError tirtc_audio_output_stop_raw_dump(TirtcAudioOutput* output);
|
|
|
209
220
|
TirtcError tirtc_metrics_audio_output_get_snapshot(TirtcAudioOutput* output,
|
|
210
221
|
TirtcAudioOutputMetricsSnapshot* out_snapshot);
|
|
211
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Copies the current or cached audio output diagnostic snapshot.
|
|
225
|
+
*
|
|
226
|
+
* The output owns the underlying media downlink. Callers provide only `out_snapshot` storage and do
|
|
227
|
+
* not receive ownership of any runtime object. The function returns `TIRTC_ERROR_INVALID_ARGUMENT`
|
|
228
|
+
* for null arguments and does not emit output callbacks or change output state.
|
|
229
|
+
*/
|
|
230
|
+
TirtcError tirtc_audio_output_get_debug_snapshot(TirtcAudioOutput* output,
|
|
231
|
+
TirtcAudioOutputDebugSnapshot* out_snapshot);
|
|
232
|
+
|
|
212
233
|
#ifdef __cplusplus
|
|
213
234
|
}
|
|
214
235
|
#endif
|
|
@@ -48,6 +48,23 @@ typedef struct TirtcVideoOutputMetricsSnapshot {
|
|
|
48
48
|
TirtcPendingDurationMetrics pending;
|
|
49
49
|
} TirtcVideoOutputMetricsSnapshot;
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Diagnostic facts currently known for a video output.
|
|
53
|
+
*
|
|
54
|
+
* The snapshot is a caller-owned value copy. `resolved_decoder_backend` is the runtime route that
|
|
55
|
+
* has actually locked, so AUTO fallback reports the concrete backend family instead of the request.
|
|
56
|
+
* Zero values mean no current fact or only cached zero-state is available. Additive changes require
|
|
57
|
+
* a new V2 struct/function instead of extending this layout.
|
|
58
|
+
*/
|
|
59
|
+
typedef struct TirtcVideoOutputDebugSnapshot {
|
|
60
|
+
TirtcMediaCodec codec;
|
|
61
|
+
TirtcVideoBitstreamFormat bitstream_format;
|
|
62
|
+
uint32_t width;
|
|
63
|
+
uint32_t height;
|
|
64
|
+
TirtcVideoDecoderPreference requested_decoder_preference;
|
|
65
|
+
TirtcVideoDecoderBackendKind resolved_decoder_backend;
|
|
66
|
+
} TirtcVideoOutputDebugSnapshot;
|
|
67
|
+
|
|
51
68
|
typedef struct TirtcVideoOutputOptions {
|
|
52
69
|
TirtcVideoDecoderPreference decoder_preference;
|
|
53
70
|
} TirtcVideoOutputOptions;
|
|
@@ -201,6 +218,17 @@ TirtcError tirtc_video_output_stop_raw_dump(TirtcVideoOutput* output);
|
|
|
201
218
|
TirtcError tirtc_metrics_video_output_get_snapshot(TirtcVideoOutput* output,
|
|
202
219
|
TirtcVideoOutputMetricsSnapshot* out_snapshot);
|
|
203
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Copies the current or cached video output diagnostic snapshot.
|
|
223
|
+
*
|
|
224
|
+
* The output owns the underlying media downlink and the returned data is only a value copy. Use
|
|
225
|
+
* this for diagnostics and UI visibility, not to drive decoder selection. The function returns
|
|
226
|
+
* `TIRTC_ERROR_INVALID_ARGUMENT` for null arguments and does not emit output callbacks or change
|
|
227
|
+
* output state.
|
|
228
|
+
*/
|
|
229
|
+
TirtcError tirtc_video_output_get_debug_snapshot(TirtcVideoOutput* output,
|
|
230
|
+
TirtcVideoOutputDebugSnapshot* out_snapshot);
|
|
231
|
+
|
|
204
232
|
#ifdef __cplusplus
|
|
205
233
|
}
|
|
206
234
|
#endif
|
|
@@ -9,8 +9,6 @@ typedef enum TirtcError {
|
|
|
9
9
|
TIRTC_ERROR_OK = 0,
|
|
10
10
|
TIRTC_ERROR_INVALID_ARGUMENT = 6000,
|
|
11
11
|
TIRTC_ERROR_NOT_INITIALIZED = 6001,
|
|
12
|
-
TIRTC_ERROR_INTERNAL = 6002,
|
|
13
|
-
TIRTC_ERROR_NOT_READY = 6003,
|
|
14
12
|
TIRTC_ERROR_UNSUPPORTED_LOOP_POLICY = 6004,
|
|
15
13
|
TIRTC_ERROR_SOURCE_HASH_MISMATCH = 6005,
|
|
16
14
|
TIRTC_ERROR_ALREADY_STOPPED = 6006,
|
|
@@ -52,6 +50,47 @@ typedef enum TirtcError {
|
|
|
52
50
|
TIRTC_ERROR_VIDEO_DECODER_RUNTIME_FAILED = 6040,
|
|
53
51
|
TIRTC_ERROR_VIDEO_OUTPUT_TARGET_UNAVAILABLE = 6041,
|
|
54
52
|
TIRTC_ERROR_VIDEO_OUTPUT_RENDER_FAILED = 6042,
|
|
53
|
+
TIRTC_ERROR_RESOURCE_EXHAUSTED = 6043,
|
|
54
|
+
TIRTC_ERROR_FILE_OPEN_FAILED = 6044,
|
|
55
|
+
TIRTC_ERROR_FILE_READ_FAILED = 6045,
|
|
56
|
+
TIRTC_ERROR_FILE_WRITE_FAILED = 6046,
|
|
57
|
+
TIRTC_ERROR_HTTP_REQUEST_FAILED = 6047,
|
|
58
|
+
TIRTC_ERROR_LOG_EXPORT_FAILED = 6048,
|
|
59
|
+
TIRTC_ERROR_LOG_UPLOAD_FAILED = 6049,
|
|
60
|
+
TIRTC_ERROR_S3_UPLOAD_FAILED = 6050,
|
|
61
|
+
TIRTC_ERROR_AUDIO_INPUT_OPEN_FAILED = 6051,
|
|
62
|
+
TIRTC_ERROR_AUDIO_INPUT_RUNTIME_FAILED = 6052,
|
|
63
|
+
TIRTC_ERROR_AUDIO_OUTPUT_OPEN_FAILED = 6053,
|
|
64
|
+
TIRTC_ERROR_AUDIO_OUTPUT_RUNTIME_FAILED = 6054,
|
|
65
|
+
TIRTC_ERROR_AUDIO_PROCESSING_INITIALIZATION_FAILED = 6055,
|
|
66
|
+
TIRTC_ERROR_AUDIO_PROCESSING_RUNTIME_FAILED = 6056,
|
|
67
|
+
TIRTC_ERROR_VIDEO_ENCODER_RUNTIME_FAILED = 6057,
|
|
68
|
+
TIRTC_ERROR_VIDEO_PROCESSING_RUNTIME_FAILED = 6058,
|
|
69
|
+
TIRTC_ERROR_VIDEO_INPUT_OPEN_FAILED = 6059,
|
|
70
|
+
TIRTC_ERROR_VIDEO_INPUT_RUNTIME_FAILED = 6060,
|
|
71
|
+
TIRTC_ERROR_VIDEO_OUTPUT_OPEN_FAILED = 6061,
|
|
72
|
+
TIRTC_ERROR_MEDIA_UPLINK_CREATE_FAILED = 6062,
|
|
73
|
+
TIRTC_ERROR_MEDIA_UPLINK_START_FAILED = 6063,
|
|
74
|
+
TIRTC_ERROR_MEDIA_DOWNLINK_DECODE_FAILED = 6064,
|
|
75
|
+
TIRTC_ERROR_MEDIA_RAW_DUMP_FAILED = 6065,
|
|
76
|
+
TIRTC_ERROR_FACADE_RUNTIME_FAILED = 6066,
|
|
77
|
+
TIRTC_ERROR_LOG_WRITE_FAILED = 6067,
|
|
78
|
+
TIRTC_ERROR_AUDIO_ENCODER_RUNTIME_FAILED = 6068,
|
|
79
|
+
TIRTC_ERROR_AUDIO_DECODER_RUNTIME_FAILED = 6069,
|
|
80
|
+
TIRTC_ERROR_HTTP_CLIENT_UNAVAILABLE = 6070,
|
|
81
|
+
TIRTC_ERROR_HTTP_TLS_UNSUPPORTED = 6071,
|
|
82
|
+
TIRTC_ERROR_UPLOAD_TOKEN_EXPIRED = 6072,
|
|
83
|
+
TIRTC_ERROR_STREAM_ID_IN_USE = 6073,
|
|
84
|
+
TIRTC_ERROR_VIDEO_PREVIEW_IN_USE = 6074,
|
|
85
|
+
TIRTC_ERROR_FACADE_PEER_ID_UNAVAILABLE = 6075,
|
|
86
|
+
TIRTC_ERROR_MEDIA_DOWNLINK_QUEUE_FULL = 6076,
|
|
87
|
+
TIRTC_ERROR_MEDIA_DOWNLINK_OUTPUT_PENDING = 6077,
|
|
88
|
+
TIRTC_ERROR_TRANSPORT_INVALID_HANDLE = 6078,
|
|
89
|
+
TIRTC_ERROR_VIDEO_ENCODER_INPUT_PENDING = 6079,
|
|
90
|
+
TIRTC_ERROR_VIDEO_ENCODER_OUTPUT_PENDING = 6080,
|
|
91
|
+
TIRTC_ERROR_VIDEO_DECODER_INPUT_PENDING = 6081,
|
|
92
|
+
TIRTC_ERROR_VIDEO_DECODER_OUTPUT_PENDING = 6082,
|
|
93
|
+
TIRTC_ERROR_MEDIA_UPLINK_INPUT_MODE_MISMATCH = 6083,
|
|
55
94
|
} TirtcError;
|
|
56
95
|
|
|
57
96
|
const char* tirtc_error_to_string(TirtcError error);
|
|
@@ -86,6 +86,33 @@ typedef struct TirtcMediaDownlinkVideoMetricsSnapshot {
|
|
|
86
86
|
TirtcMediaDownlinkPendingMetricsSnapshot pending;
|
|
87
87
|
} TirtcMediaDownlinkVideoMetricsSnapshot;
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Diagnostic facts currently known by an audio downlink.
|
|
91
|
+
*
|
|
92
|
+
* The snapshot is a value copy into caller-owned storage. `codec` is
|
|
93
|
+
* `TIRTC_MEDIA_CODEC_NONE` until the downlink accepts a valid encoded audio frame.
|
|
94
|
+
*/
|
|
95
|
+
typedef struct TirtcMediaDownlinkAudioDebugSnapshot {
|
|
96
|
+
TirtcMediaCodec codec;
|
|
97
|
+
} TirtcMediaDownlinkAudioDebugSnapshot;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Diagnostic facts currently known by a video downlink.
|
|
101
|
+
*
|
|
102
|
+
* The snapshot is a value copy into caller-owned storage. Zero values mean the downlink has not
|
|
103
|
+
* observed the corresponding fact since start/reset. `requested_decoder_preference` reflects the
|
|
104
|
+
* configured option; `resolved_decoder_backend` is only set after the runtime locks a concrete
|
|
105
|
+
* decode route.
|
|
106
|
+
*/
|
|
107
|
+
typedef struct TirtcMediaDownlinkVideoDebugSnapshot {
|
|
108
|
+
TirtcMediaCodec codec;
|
|
109
|
+
TirtcVideoBitstreamFormat bitstream_format;
|
|
110
|
+
uint32_t width;
|
|
111
|
+
uint32_t height;
|
|
112
|
+
TirtcVideoDecoderPreference requested_decoder_preference;
|
|
113
|
+
TirtcVideoDecoderBackendKind resolved_decoder_backend;
|
|
114
|
+
} TirtcMediaDownlinkVideoDebugSnapshot;
|
|
115
|
+
|
|
89
116
|
TirtcError tirtc_media_downlink_audio_create(TirtcMediaDownlinkAudio** out_downlink);
|
|
90
117
|
void tirtc_media_downlink_audio_retain(TirtcMediaDownlinkAudio* downlink);
|
|
91
118
|
void tirtc_media_downlink_audio_release(TirtcMediaDownlinkAudio* downlink);
|
|
@@ -147,6 +174,24 @@ TirtcError tirtc_media_downlink_video_get_metrics_snapshot(
|
|
|
147
174
|
TirtcMediaDownlinkVideo* downlink, TirtcMediaDownlinkVideoMetricsSnapshot* out_snapshot);
|
|
148
175
|
void tirtc_media_downlink_video_reset_metrics_session(TirtcMediaDownlinkVideo* downlink);
|
|
149
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Copies the current audio downlink diagnostic snapshot.
|
|
179
|
+
*
|
|
180
|
+
* This call does not start, stop, flush, or otherwise change the downlink. It returns
|
|
181
|
+
* `TIRTC_ERROR_INVALID_ARGUMENT` when `downlink` or `out_snapshot` is null.
|
|
182
|
+
*/
|
|
183
|
+
TirtcError tirtc_media_downlink_audio_get_debug_snapshot(
|
|
184
|
+
TirtcMediaDownlinkAudio* downlink, TirtcMediaDownlinkAudioDebugSnapshot* out_snapshot);
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Copies the current video downlink diagnostic snapshot.
|
|
188
|
+
*
|
|
189
|
+
* This call does not start, stop, flush, or otherwise change the downlink. It returns
|
|
190
|
+
* `TIRTC_ERROR_INVALID_ARGUMENT` when `downlink` or `out_snapshot` is null.
|
|
191
|
+
*/
|
|
192
|
+
TirtcError tirtc_media_downlink_video_get_debug_snapshot(
|
|
193
|
+
TirtcMediaDownlinkVideo* downlink, TirtcMediaDownlinkVideoDebugSnapshot* out_snapshot);
|
|
194
|
+
|
|
150
195
|
#ifdef __cplusplus
|
|
151
196
|
}
|
|
152
197
|
#endif
|
|
@@ -26,6 +26,19 @@ typedef enum TirtcVideoDecoderPreference {
|
|
|
26
26
|
TIRTC_VIDEO_DECODER_PREFERENCE_HARDWARE = 2,
|
|
27
27
|
} TirtcVideoDecoderPreference;
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Backend family that is actually handling a video decoder route.
|
|
31
|
+
*
|
|
32
|
+
* `UNKNOWN` means the runtime has not locked a decoder route or the current snapshot cannot prove
|
|
33
|
+
* one. The enum intentionally reports only the supported backend family; platform-specific decoder
|
|
34
|
+
* names and native handles are not part of this public surface.
|
|
35
|
+
*/
|
|
36
|
+
typedef enum TirtcVideoDecoderBackendKind {
|
|
37
|
+
TIRTC_VIDEO_DECODER_BACKEND_KIND_UNKNOWN = 0,
|
|
38
|
+
TIRTC_VIDEO_DECODER_BACKEND_KIND_SOFTWARE = 1,
|
|
39
|
+
TIRTC_VIDEO_DECODER_BACKEND_KIND_HARDWARE = 2,
|
|
40
|
+
} TirtcVideoDecoderBackendKind;
|
|
41
|
+
|
|
29
42
|
typedef enum TirtcVideoEncoderBackendKind {
|
|
30
43
|
TIRTC_VIDEO_ENCODER_BACKEND_KIND_SOFTWARE = 1,
|
|
31
44
|
TIRTC_VIDEO_ENCODER_BACKEND_KIND_HARDWARE = 2,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
platform=macos-arm64
|
|
2
2
|
profile=full
|
|
3
|
-
staged_at_utc=2026-04-
|
|
3
|
+
staged_at_utc=2026-04-30T09:50:11Z
|
|
4
4
|
source_sdk=/Users/allenfeng/Development/Repositories/tirtc-nexus/tirtc-matrix/.build/sdk/macos-arm64
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
bfc096be1484ac2b1c2776ccabfa2a4c6a982e869abf875192ff06fad85e82ca include/tirtc/audio.h
|
|
7
7
|
6d972ccfe150a3b4f2d7f18fa92b3ade9210c1c8bb754d061ac6b7997b59e2cb include/tirtc/audio_codec.h
|
|
8
8
|
7bacbdb2d8bb10d6444036a8fef42f2a8e3ea34dfc38e165ee678d61f189db41 include/tirtc/audio_frame.h
|
|
9
9
|
fb8ea35263167c33487bd3aa503c26ed2dfbf97877f7bda92c10065cd5c97c13 include/tirtc/audio_io.h
|
|
@@ -13,17 +13,17 @@ c2e1f31dcc75be461c577d18b1cebe32774f212d51cb4dd2a5b5a9bfe62b693e include/tirtc/
|
|
|
13
13
|
51cbc911fe9f9834046f0e0a1a7cdd814a8e194a615894a8b4d11f9e5f095610 include/tirtc/audio_io_windows.h
|
|
14
14
|
21f60729117260a44af22c1af986ef17d22673b102b7b7a035f492d0665cce16 include/tirtc/audio_processing.h
|
|
15
15
|
0ca7c3c630b1242f51a0fd8154097c0a332b4c816a5707090e4381719852998c include/tirtc/audio_sample_rate.h
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
58807ba56770f38f47aec995661cadf9d3c1d6ea7bfc940767f1ce67317c7546 include/tirtc/av.h
|
|
17
|
+
0f3e2f454c35e8c2f79bdc93ed77f9f1622751e5a05defa8c9d4213ed8a797c5 include/tirtc/error.h
|
|
18
18
|
ae805545a9515edc9b94262e72ad2c7b7d649288166f4daeb450d8a55e82ae0b include/tirtc/foundation/build_info.h
|
|
19
19
|
7cf8b372a3d48d4de4a65a04c7f102281a7b42cebb9ec247853d3c53afb63b6a include/tirtc/http.h
|
|
20
20
|
70bbf93b84d9d1a85f376d9986de570c1f658319e1e5ab6d621f7a4d41033f5c include/tirtc/logging.h
|
|
21
21
|
7e2f7f81afe37e22f5414d9db32438edd948ff775230c3a0a17ff9ac1a0b560e include/tirtc/media_codec.h
|
|
22
|
-
|
|
22
|
+
ca63fe4fa0c787f20923e264e116fa6d7cb8194a227c03be4e9843d0ce5a9864 include/tirtc/media_downlink.h
|
|
23
23
|
e64191a39004165cdcd11b2ca824af34d4bfe02f7ec3c3101fa9291f56488c30 include/tirtc/media_uplink.h
|
|
24
24
|
489f6c9caa3e4094566b660ef0a002a39c66c1956ef0a1bdb6eacca3798c849a include/tirtc/transport.h
|
|
25
25
|
bb9c1bf46f2ab51a9f7adb211276c8563b09e7968031c0c6abeebc0eddd66acb include/tirtc/trp.h
|
|
26
|
-
|
|
26
|
+
92b3db6e2cb02265ad5db01881edce9d4e095b1dadf449dce5d8bb5362957e33 include/tirtc/video_codec.h
|
|
27
27
|
e51379666c199588cc33279ccf52248035d1cae3d1d468b1615ebf29f0b39c9c include/tirtc/video_frame.h
|
|
28
28
|
2a02645d82c58d433c7306a9f0bcd31d0f3e560b63822f7e80919761b81a6284 include/tirtc/video_io.h
|
|
29
29
|
9930dce5e8e2b12a1ab28ee91f3fb46f6cf3487e515ea2b4ec0e00009bd5f070 include/tirtc/video_io_android.h
|
|
@@ -35,13 +35,13 @@ cae0bbeb884e5466a56da15182c78cc22baab6c743f349a58d3595f623333585 include/tirtc/
|
|
|
35
35
|
8db86d6714264047e8fd4086ddd7315722d675749719e6175f89eb5a636b48a1 lib/libTiRTC.a
|
|
36
36
|
b39daee6a3d39bf0ca20c45084601133c4198de8dca848dcff6dd9c70ae99016 lib/libcrypto.a
|
|
37
37
|
c052857ef315e3d61db9c862cad10709a3a6b2487dc41799cbe4d74a805de875 lib/libcrypto.dylib
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
d6f03b56a9de8db6b283acbdd9fc2805d23d672f4cb88749f55a627443b2519f lib/libmatrix_runtime_audio.a
|
|
39
|
+
7524498dba92087ba33853290db0cfaa0ec79b50ffdf22c8e35b0484c24af7cc lib/libmatrix_runtime_facade.a
|
|
40
|
+
05687add5f3f27adea62568b9d42be52659a494500cce0245d601da566aa45e3 lib/libmatrix_runtime_foundation_http.a
|
|
41
|
+
89af61f8a48b2c7cfa9c80de8b9a708bca4ac2b1b4b2929d1d932a5c4d422501 lib/libmatrix_runtime_foundation_logging.a
|
|
42
|
+
6a61357646112e1427db956ba87766838b51bdd7d8aec43ec07c2aba20570ee7 lib/libmatrix_runtime_media.a
|
|
43
|
+
cc39fbeacd2c8cd6b508cd3300bf8fd5b6a93f6d2d19b160b65ed03deca777c4 lib/libmatrix_runtime_transport.a
|
|
44
|
+
7ab317069e6bdeb3d24d215cd7bb6f298ea47cf1cff43ac36460aaab7effbd8d lib/libmatrix_runtime_video.a
|
|
45
45
|
c11c65d373a127028350c41fa58cd2d1223f2b5d70a84e13b115d90daaba25ca lib/libssl.a
|
|
46
46
|
ef1c1104bbdd2528ed7b958fb7252bd6249875f92300b0c9577d6c4bd6c0d88a lib/libssl.dylib
|
|
47
47
|
e14e846e43d64e240fa0e5745bf4e702b79d0f2442e7f768beb990610735c71b lib/libtgrtc.dylib
|
|
@@ -20,6 +20,10 @@ fail() {
|
|
|
20
20
|
exit 1
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
progress() {
|
|
24
|
+
echo "[prepare_runtime_media_dataset] progress: $*" >&2
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
require_cmd() {
|
|
24
28
|
command -v "$1" >/dev/null 2>&1 || fail "missing required command: $1"
|
|
25
29
|
}
|
|
@@ -145,6 +149,22 @@ readonly k_audio_codec="g711a"
|
|
|
145
149
|
readonly k_output_audio_format="pcm_s16"
|
|
146
150
|
readonly k_output_video_format="rgba8888"
|
|
147
151
|
|
|
152
|
+
progress "checking source media streams"
|
|
153
|
+
AUDIO_STREAM_PRESENT="$(
|
|
154
|
+
AUDIO_STREAM_JSON="$("$FFPROBE_BIN" -v error -select_streams a:0 \
|
|
155
|
+
-show_entries stream=index -of json "$SOURCE_ABS")" \
|
|
156
|
+
node <<'NODE'
|
|
157
|
+
const payload = process.env.AUDIO_STREAM_JSON;
|
|
158
|
+
if (!payload) {
|
|
159
|
+
throw new Error('missing AUDIO_STREAM_JSON');
|
|
160
|
+
}
|
|
161
|
+
const parsed = JSON.parse(payload);
|
|
162
|
+
const stream = Array.isArray(parsed.streams) ? parsed.streams[0] : null;
|
|
163
|
+
process.stdout.write(stream ? '1' : '0');
|
|
164
|
+
NODE
|
|
165
|
+
)"
|
|
166
|
+
[[ "$AUDIO_STREAM_PRESENT" == "1" ]] || fail "invalid_source_media: source mp4 is missing an audio stream: $SOURCE_ABS"
|
|
167
|
+
|
|
148
168
|
VIDEO_STREAM_FIELDS="$(
|
|
149
169
|
VIDEO_STREAM_JSON="$("$FFPROBE_BIN" -v error -select_streams v:0 \
|
|
150
170
|
-show_entries stream=width,height,bit_rate -of json "$SOURCE_ABS")" \
|
|
@@ -215,6 +235,7 @@ fi
|
|
|
215
235
|
MANIFEST_PATH="$ASSETS_DIR/manifest.json"
|
|
216
236
|
|
|
217
237
|
if [[ -f "$MANIFEST_PATH" && "$OVERWRITE" -ne 1 ]]; then
|
|
238
|
+
progress "using cached prepared media assets"
|
|
218
239
|
emit_result "$ASSETS_DIR" "$MANIFEST_PATH" true
|
|
219
240
|
exit 0
|
|
220
241
|
fi
|
|
@@ -259,6 +280,7 @@ else
|
|
|
259
280
|
video_encode_args+=(-crf 18)
|
|
260
281
|
fi
|
|
261
282
|
|
|
283
|
+
progress "encoding h264 video track"
|
|
262
284
|
"$FFMPEG_BIN" -hide_banner -loglevel error -y \
|
|
263
285
|
-i "$SOURCE_ABS" \
|
|
264
286
|
-an \
|
|
@@ -287,6 +309,7 @@ else
|
|
|
287
309
|
video_h265_encode_args+=(-crf 23)
|
|
288
310
|
fi
|
|
289
311
|
|
|
312
|
+
progress "encoding h265 video track"
|
|
290
313
|
"$FFMPEG_BIN" -hide_banner -loglevel error -y \
|
|
291
314
|
-i "$SOURCE_ABS" \
|
|
292
315
|
-an \
|
|
@@ -296,6 +319,7 @@ fi
|
|
|
296
319
|
|
|
297
320
|
mjpeg_frame_dir="$ASSETS_DIR/video/mjpeg_frames"
|
|
298
321
|
mkdir -p "$mjpeg_frame_dir"
|
|
322
|
+
progress "extracting mjpeg video frames"
|
|
299
323
|
"$FFMPEG_BIN" -hide_banner -loglevel error -y \
|
|
300
324
|
-i "$SOURCE_ABS" \
|
|
301
325
|
-vf "fps=1/${k_mjpeg_extract_interval_seconds},scale=${TARGET_VIDEO_WIDTH}:${TARGET_VIDEO_HEIGHT}:flags=lanczos" \
|
|
@@ -311,6 +335,7 @@ if ! find "$mjpeg_frame_dir" -type f -name 'frame_*.jpg' | grep -q .; then
|
|
|
311
335
|
"$mjpeg_frame_dir/frame_000001.jpg"
|
|
312
336
|
fi
|
|
313
337
|
|
|
338
|
+
progress "encoding 8k g711a audio track"
|
|
314
339
|
"$FFMPEG_BIN" -hide_banner -loglevel error -y \
|
|
315
340
|
-i "$SOURCE_ABS" \
|
|
316
341
|
-vn \
|
|
@@ -320,6 +345,7 @@ fi
|
|
|
320
345
|
-f alaw \
|
|
321
346
|
"$AUDIO_PATH"
|
|
322
347
|
|
|
348
|
+
progress "encoding 16k g711a audio track"
|
|
323
349
|
"$FFMPEG_BIN" -hide_banner -loglevel error -y \
|
|
324
350
|
-i "$SOURCE_ABS" \
|
|
325
351
|
-vn \
|
|
@@ -329,6 +355,7 @@ fi
|
|
|
329
355
|
-f alaw \
|
|
330
356
|
"$AUDIO_16K_PATH"
|
|
331
357
|
|
|
358
|
+
progress "indexing h264 video packets"
|
|
332
359
|
VIDEO_PACKET_INDEX_PATH="$VIDEO_H264_PACKET_INDEX_PATH" \
|
|
333
360
|
VIDEO_PATH="$VIDEO_H264_PATH" \
|
|
334
361
|
VIDEO_FPS="$k_video_fps" \
|
|
@@ -426,6 +453,7 @@ for (let index = 0; index < packetOffsets.length; index += 1) {
|
|
|
426
453
|
fs.writeFileSync(outputPath, `${lines.join('\n')}\n`, 'utf8');
|
|
427
454
|
NODE
|
|
428
455
|
|
|
456
|
+
progress "indexing h265 video packets"
|
|
429
457
|
VIDEO_PACKET_INDEX_PATH="$VIDEO_H265_PACKET_INDEX_PATH" \
|
|
430
458
|
VIDEO_PATH="$VIDEO_H265_PATH" \
|
|
431
459
|
VIDEO_FPS="$k_video_fps" \
|
|
@@ -523,6 +551,7 @@ for (let index = 0; index < packetOffsets.length; index += 1) {
|
|
|
523
551
|
fs.writeFileSync(outputPath, `${lines.join('\n')}\n`, 'utf8');
|
|
524
552
|
NODE
|
|
525
553
|
|
|
554
|
+
progress "indexing mjpeg video packets"
|
|
526
555
|
VIDEO_MJPEG_PATH="$VIDEO_MJPEG_PATH" \
|
|
527
556
|
VIDEO_MJPEG_PACKET_INDEX_PATH="$VIDEO_MJPEG_PACKET_INDEX_PATH" \
|
|
528
557
|
MJPEG_FRAME_DIR="$mjpeg_frame_dir" \
|
|
@@ -578,6 +607,7 @@ for (let index = 0; index < packetCount; index += 1) {
|
|
|
578
607
|
fs.writeFileSync(indexPath, `${lines.join('\n')}\n`, 'utf8');
|
|
579
608
|
NODE
|
|
580
609
|
|
|
610
|
+
progress "indexing 8k g711a audio packets"
|
|
581
611
|
AUDIO_BYTES="$(wc -c < "$AUDIO_PATH" | tr -d '[:space:]')"
|
|
582
612
|
AUDIO_PACKET_BYTES=$((k_audio_sample_rate_hz * k_audio_packet_duration_ms / 1000))
|
|
583
613
|
[[ "$AUDIO_PACKET_BYTES" -gt 0 ]] || fail "invalid audio packet bytes"
|
|
@@ -609,6 +639,7 @@ AUDIO_PACKET_COUNT=$((AUDIO_BYTES / AUDIO_PACKET_BYTES))
|
|
|
609
639
|
done
|
|
610
640
|
} > "$AUDIO_PACKET_INDEX_PATH"
|
|
611
641
|
|
|
642
|
+
progress "indexing 16k g711a audio packets"
|
|
612
643
|
AUDIO_16K_BYTES="$(wc -c < "$AUDIO_16K_PATH" | tr -d '[:space:]')"
|
|
613
644
|
AUDIO_16K_PACKET_BYTES=$((k_audio_sample_rate_16k_hz * k_audio_packet_duration_ms / 1000))
|
|
614
645
|
[[ "$AUDIO_16K_PACKET_BYTES" -gt 0 ]] || fail "invalid 16k audio packet bytes"
|
|
@@ -640,6 +671,7 @@ AUDIO_16K_PACKET_COUNT=$((AUDIO_16K_BYTES / AUDIO_16K_PACKET_BYTES))
|
|
|
640
671
|
done
|
|
641
672
|
} > "$AUDIO_16K_PACKET_INDEX_PATH"
|
|
642
673
|
|
|
674
|
+
progress "writing prepared media manifest"
|
|
643
675
|
cat > "$MANIFEST_PATH" <<JSON
|
|
644
676
|
{
|
|
645
677
|
"schema_version": ${k_schema_version},
|