tirtc-electron
v2.4.2
Published
TiRTC Electron SDK for macOS arm64, macOS x64, and Windows x64 preview
Readme
tirtc-electron
tirtc-electron is the Electron main-process SDK for an active TiRTC client and Ti Cloud Storage. Version 2.4.2 contains self-contained native closures for macOS arm64, macOS x64, and Windows x64.
In 2.4.2, Ti Cloud Storage replay progress continues to follow media consumption after the source finishes delivering data. Source completion and output playback completion retain their distinct meanings.
Install and support
Install the stable package or pin the exact version:
npm install --save-exact [email protected]
# or: npm install tirtc-electron| Tuple | Product status |
| --- | --- |
| macOS arm64 | native behavior qualification |
| macOS x64 | Rosetta x86_64 behavior qualification |
| Windows x64 | preview-static-qualified; runtime, GUI, RTC, Ti Cloud Storage, and lifecycle are not-run |
The qualification toolchain is Electron 43.3.0, Electron Builder 26.15.7, TypeScript 5.9.2, and Node-API 9. The npm package never downloads or compiles Runtime during install or load.
Process and credential boundary
Create all SDK objects after app.whenReady() in the main process. The package derives its writable Runtime root from Electron's app.getPath('userData'); call app.setPath('userData', absolutePath) before initialization if the application needs another root.
App ID and short-lived RTC/Ti Cloud Storage Tokens come from the application's server or existing credential flow. Do not generate, persist, or send them to Renderer. Keep contextIsolation and sandbox enabled, keep nodeIntegration disabled, and expose only the application's narrow typed preload methods.
RTC client path
import {
TiRtc,
TiRtcAudioInput,
TiRtcAudioOutput,
TiRtcConn,
TiRtcVideoOutput,
TiVideoView,
} from 'tirtc-electron';
TiRtc.init({appId, endpoint});
const connection = new TiRtcConn();
const microphone = new TiRtcAudioInput();
const audio = new TiRtcAudioOutput();
const video = new TiRtcVideoOutput();
const view = new TiVideoView(browserWindow, {x: 0, y: 0, width: 640, height: 360});
connection.onStateChanged = (state, error) => {
if (state === 'connected') {
connection.subscribeAudio(10);
connection.subscribeVideo(11);
} else if (state === 'disconnected' && error) {
console.error(error.code, error.nativeCode);
}
};
audio.attach(connection, 10);
video.mount(view);
video.attach(connection, 11);
microphone.attach(connection, 12);
microphone.start();
connection.connect({remoteId, token});JavaScript type, enum, range, and option-combination errors throw TypeError before entering Native. Runtime state, device, network, authorization, resource, and file failures throw or reject TiRtcError; inspect its string code and diagnostic nativeCode. Accepted connection/media commands complete through object state callbacks.
Dispose in reverse ownership order: stop tasks, copy and delete returned temporary files, stop and detach the microphone, detach/unmount/dispose outputs, dispose the view, disconnect/dispose the connection, then TiRtc.shutdown().
Ti Cloud Storage path
import {
TiCloudStorage,
TiCloudStorageAudioOutput,
TiCloudStorageVideoOutput,
TiVideoView,
} from 'tirtc-electron';
TiCloudStorage.init({appId, endpoint});
const storage = new TiCloudStorage(token);
const recordings = await storage.listRecordings({startTimeMs, endTimeMs});
const replay = storage.createReplay();
const audio = new TiCloudStorageAudioOutput();
const video = new TiCloudStorageVideoOutput();
const view = new TiVideoView(browserWindow, bounds);
audio.attach(replay, audioChannelId);
video.mount(view);
video.attach(replay, videoChannelId);
replay.play({startTimeMs: recordings[0].startTimeMs, endTimeMs: recordings[0].endTimeMs});Replay supports pause, resume, seek, numeric speeds 0.125..8, snapshots, play-time recording, and direct range export. If an operation reports token-expired, obtain a new Token, call storage.updateToken(newToken), and explicitly retry the operation.
Teardown in reverse order: stop recording/export work, copy and delete returned temporary files, stop replay, detach/unmount/dispose outputs, dispose the view and replay, dispose storage, then TiCloudStorage.shutdown().
Temporary media
Recording, snapshot, and export results are private Runtime-cache files. Copy them to an application-owned absolute path, then call the file object's idempotent delete(). The canonical desktop Example writes a unique name directly to Downloads and never overwrites an existing file.
import {constants, copyFile} from 'node:fs/promises';
const task = connection.startRecording({videoStreamId: 11, audioStreamId: 10});
const media = await task.stop();
await copyFile(media.path, destinationPath, constants.COPYFILE_EXCL);
await media.delete();If the copy fails, retain the cache source so the user can retry.
Logging without product initialization
import {TiRtcLogging} from 'tirtc-electron';
const logId = await TiRtcLogging.upload();Log upload is process-wide single-flight and can establish a temporary logging-only Runtime lease. It does not enable product constructors or connections. The resolved log ID is non-empty; a concurrent upload rejects with TiRtcError code in-use.
Electron Builder
The canonical Example is the packaging reference. Set one target tuple and build a directory:
cd electron/tirtc_electron/example
npm ci
TIRTC_ELECTRON_TARGET_TUPLE=darwin-arm64 npm run package:dir -- --mac --arm64Use darwin-x64 with --mac --x64 or win32-x64 with --win --x64. The Builder hook removes the two unused native tuples after ASAR creation, keeps the selected .node plus its Runtime/Nano libraries in app.asar.unpacked, and leaves no duplicate native closure in app.asar. The application owns signing, notarization, entitlements, microphone permission text, and distribution.
Canonical Example and public Sample
example/ is the canonical source. It follows the Flutter desktop Example's visible pages, copy, state, and interaction, including disabled scan controls, system Audio Input only, and direct Downloads saves. Its main process owns SDK resources and credentials; Renderer only receives serializable state/actions.
After publication the exact-version projection is available at [email protected]:tangeai/tirtc-api-samples.git under electron/. It installs only the published npm package and retains the same Builder configuration.
Local owner validation
Build all three payloads, select one candidate, then validate a clean consumer:
electron/tirtc_electron/script/electron_verify.sh --mode build-payload \
--tuple darwin-arm64 --runtime-root <macos-arm64-runtime-root> --output-root .build/electron-sdk
electron/tirtc_electron/script/electron_verify.sh --mode build-payload \
--tuple darwin-x64 --runtime-root <macos-x64-runtime-root> --output-root .build/electron-sdk
electron/tirtc_electron/script/electron_verify.sh --mode build-payload \
--tuple win32-x64 --runtime-root <windows-x64-runtime-root> --output-root .build/electron-sdk
node electron/tirtc_electron/script/package_candidate.mjs \
--darwin-arm64-payload .build/electron-sdk/payload/darwin-arm64 \
--darwin-x64-payload .build/electron-sdk/payload/darwin-x64 \
--windows-x64-payload .build/electron-sdk/payload/win32-x64 \
--source-commit <40-hex-source-commit> \
--output .build/electron-sdk/candidate
electron/tirtc_electron/script/electron_verify.sh --mode candidate-contract \
--candidate .build/electron-sdk/candidate/tirtc-electron-2.4.2.tgz \
--output-root .build/electron-sdkThe electron-test owner runs macOS arm64 and macOS x64 behavior lanes separately. Windows cross-build/package checks produce only preview-static-qualified evidence.
See the exact public declarations, RTC reference, Ti Cloud Storage reference, and breaking migration.
