@absolutejs/voice 0.0.22-beta.320 → 0.0.22-beta.321
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 +122 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4882,3 +4882,125 @@ Browser and framework helpers sit on top of the same connection core:
|
|
|
4882
4882
|
- `VoiceStreamService` in `@absolutejs/voice/angular`
|
|
4883
4883
|
|
|
4884
4884
|
For plain HTML or HTMX flows, use `@absolutejs/voice/client` directly.
|
|
4885
|
+
|
|
4886
|
+
### Browser Media Proof
|
|
4887
|
+
|
|
4888
|
+
If your app owns a browser `RTCPeerConnection`, pass it through `browserMedia` so AbsoluteJS can persist real `RTCPeerConnection.getStats()` evidence and feed production readiness. The default WebSocket microphone flow does not require this; this is for WebRTC voice surfaces where browser transport quality matters.
|
|
4889
|
+
|
|
4890
|
+
Server route setup:
|
|
4891
|
+
|
|
4892
|
+
```ts
|
|
4893
|
+
import {
|
|
4894
|
+
createVoiceBrowserMediaRoutes,
|
|
4895
|
+
createVoiceProductionReadinessRoutes,
|
|
4896
|
+
getLatestVoiceBrowserMediaReport
|
|
4897
|
+
} from '@absolutejs/voice';
|
|
4898
|
+
|
|
4899
|
+
app
|
|
4900
|
+
.use(createVoiceBrowserMediaRoutes({ store: runtime.traces }))
|
|
4901
|
+
.use(
|
|
4902
|
+
createVoiceProductionReadinessRoutes({
|
|
4903
|
+
browserMedia: () =>
|
|
4904
|
+
getLatestVoiceBrowserMediaReport({ store: runtime.traces }),
|
|
4905
|
+
links: {
|
|
4906
|
+
browserMedia: '/voice/browser-media'
|
|
4907
|
+
}
|
|
4908
|
+
})
|
|
4909
|
+
);
|
|
4910
|
+
```
|
|
4911
|
+
|
|
4912
|
+
Shared stream options:
|
|
4913
|
+
|
|
4914
|
+
```ts
|
|
4915
|
+
const browserMedia = {
|
|
4916
|
+
getPeerConnection: () => peerConnection,
|
|
4917
|
+
maxJitterMs: 30,
|
|
4918
|
+
maxPacketLossRatio: 0.02,
|
|
4919
|
+
maxRoundTripTimeMs: 250,
|
|
4920
|
+
requireConnectedCandidatePair: true,
|
|
4921
|
+
requireLiveAudioTrack: true
|
|
4922
|
+
};
|
|
4923
|
+
```
|
|
4924
|
+
|
|
4925
|
+
React:
|
|
4926
|
+
|
|
4927
|
+
```tsx
|
|
4928
|
+
import { useRef } from 'react';
|
|
4929
|
+
import { useVoiceStream } from '@absolutejs/voice/react';
|
|
4930
|
+
|
|
4931
|
+
export function WebRTCVoice() {
|
|
4932
|
+
const peerConnection = useRef<RTCPeerConnection | null>(null);
|
|
4933
|
+
const voice = useVoiceStream('/voice/support', {
|
|
4934
|
+
browserMedia: {
|
|
4935
|
+
...browserMedia,
|
|
4936
|
+
getPeerConnection: () => peerConnection.current
|
|
4937
|
+
}
|
|
4938
|
+
});
|
|
4939
|
+
|
|
4940
|
+
return <button onClick={() => voice.close()}>End call</button>;
|
|
4941
|
+
}
|
|
4942
|
+
```
|
|
4943
|
+
|
|
4944
|
+
Vue:
|
|
4945
|
+
|
|
4946
|
+
```ts
|
|
4947
|
+
import { shallowRef } from 'vue';
|
|
4948
|
+
import { useVoiceStream } from '@absolutejs/voice/vue';
|
|
4949
|
+
|
|
4950
|
+
const peerConnection = shallowRef<RTCPeerConnection | null>(null);
|
|
4951
|
+
const voice = useVoiceStream('/voice/support', {
|
|
4952
|
+
browserMedia: {
|
|
4953
|
+
...browserMedia,
|
|
4954
|
+
getPeerConnection: () => peerConnection.value
|
|
4955
|
+
}
|
|
4956
|
+
});
|
|
4957
|
+
```
|
|
4958
|
+
|
|
4959
|
+
Svelte:
|
|
4960
|
+
|
|
4961
|
+
```ts
|
|
4962
|
+
import { createVoiceStream } from '@absolutejs/voice/svelte';
|
|
4963
|
+
|
|
4964
|
+
let peerConnection: RTCPeerConnection | null = null;
|
|
4965
|
+
const voice = createVoiceStream('/voice/support', {
|
|
4966
|
+
browserMedia: {
|
|
4967
|
+
...browserMedia,
|
|
4968
|
+
getPeerConnection: () => peerConnection
|
|
4969
|
+
}
|
|
4970
|
+
});
|
|
4971
|
+
```
|
|
4972
|
+
|
|
4973
|
+
Angular:
|
|
4974
|
+
|
|
4975
|
+
```ts
|
|
4976
|
+
import { Component, inject } from '@angular/core';
|
|
4977
|
+
import { VoiceStreamService } from '@absolutejs/voice/angular';
|
|
4978
|
+
|
|
4979
|
+
@Component({
|
|
4980
|
+
selector: 'app-webrtc-voice',
|
|
4981
|
+
template: `<button type="button" (click)="stream.close()">End call</button>`
|
|
4982
|
+
})
|
|
4983
|
+
export class WebRTCVoiceComponent {
|
|
4984
|
+
private readonly voice = inject(VoiceStreamService);
|
|
4985
|
+
private peerConnection: RTCPeerConnection | null = null;
|
|
4986
|
+
|
|
4987
|
+
readonly stream = this.voice.connect('/voice/support', {
|
|
4988
|
+
browserMedia: {
|
|
4989
|
+
...browserMedia,
|
|
4990
|
+
getPeerConnection: () => this.peerConnection
|
|
4991
|
+
}
|
|
4992
|
+
});
|
|
4993
|
+
}
|
|
4994
|
+
```
|
|
4995
|
+
|
|
4996
|
+
HTMX/plain browser:
|
|
4997
|
+
|
|
4998
|
+
```ts
|
|
4999
|
+
import { createVoiceController } from '@absolutejs/voice/client';
|
|
5000
|
+
|
|
5001
|
+
const voice = createVoiceController('/voice/support', {
|
|
5002
|
+
browserMedia
|
|
5003
|
+
});
|
|
5004
|
+
|
|
5005
|
+
voice.bindHTMX({ element: '#voice-htmx-sync' });
|
|
5006
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absolutejs/voice",
|
|
3
|
-
"version": "0.0.22-beta.
|
|
3
|
+
"version": "0.0.22-beta.321",
|
|
4
4
|
"description": "Voice primitives and Elysia plugin for AbsoluteJS",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
}
|
|
247
247
|
},
|
|
248
248
|
"dependencies": {
|
|
249
|
-
"@absolutejs/media": "0.0.1-beta.
|
|
249
|
+
"@absolutejs/media": "0.0.1-beta.5"
|
|
250
250
|
},
|
|
251
251
|
"devDependencies": {
|
|
252
252
|
"@absolutejs/absolute": "0.19.0-beta.646",
|