-
Notifications
You must be signed in to change notification settings - Fork 71
/
index.ts
72 lines (63 loc) · 2.12 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import {
AudioFrame,
AudioSource,
LocalAudioTrack,
Room,
TrackPublishOptions,
TrackSource,
dispose,
} from '@livekit/rtc-node';
import { config } from 'dotenv';
import { AccessToken } from 'livekit-server-sdk';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
config();
// create access token from API credentials
const token = new AccessToken(process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_API_SECRET, {
identity: 'example-participant',
});
token.addGrant({
room: 'example-room',
roomJoin: true,
roomCreate: true,
canPublish: true,
});
const jwt = await token.toJwt();
// set up room
const room = new Room();
await room.connect(process.env.LIVEKIT_URL, jwt, { autoSubscribe: true, dynacast: true });
console.log('connected to room', room);
// read relevant metadata from wav file
// this example assumes valid encoding little-endian
const sample = readFileSync(join(process.cwd(), './speex.wav'));
const channels = sample.readUInt16LE(22);
const sampleRate = sample.readUInt32LE(24);
const dataSize = sample.readUInt32LE(40) / 2;
// set up audio track
const source = new AudioSource(sampleRate, channels);
const track = LocalAudioTrack.createAudioTrack('audio', source);
const options = new TrackPublishOptions();
const buffer = new Int16Array(sample.buffer);
options.source = TrackSource.SOURCE_MICROPHONE;
await room.localParticipant.publishTrack(track, options).then((pub) => pub.waitForSubscription());
let written = 44; // start of WAVE data stream
const FRAME_DURATION = 1; // write 1s of audio at a time
const numSamples = sampleRate * FRAME_DURATION;
while (written < dataSize) {
const available = dataSize - written;
const frameSize = Math.min(numSamples, available);
const frame = new AudioFrame(
buffer.slice(written, written + frameSize),
sampleRate,
channels,
Math.trunc(frameSize / channels),
);
await source.captureFrame(frame);
written += frameSize;
}
await source.waitForPlayout();
// release resources allocated for audio publishing
await source.close();
await room.disconnect();
// disposes all resources, only use if no more sessions are expected
await dispose();