128 lines
2.9 KiB
Markdown
128 lines
2.9 KiB
Markdown
---
|
|
sidebar_position: 9
|
|
---
|
|
|
|
# P2P and Media API
|
|
|
|
P2P APIs send plugin data to connected peers. Media APIs play audio and contribute custom streams.
|
|
|
|
## Required Capabilities
|
|
|
|
| Method | Capability |
|
|
| --- | --- |
|
|
| `p2p.connectedPeers()` | `p2p.data` |
|
|
| `p2p.broadcastData(eventName, payload)` | `p2p.data` |
|
|
| `p2p.sendData(peerId, eventName, payload)` | `p2p.data` |
|
|
| `media.playAudioClip(request)` | `media.playAudio` |
|
|
| `media.addCustomAudioStream(request)` | `media.addAudioStream` |
|
|
| `media.addCustomVideoStream(request)` | `media.addVideoStream` |
|
|
| `media.setInputVolume(volume)` | `audio.volume` |
|
|
| `media.setOutputVolume(volume)` | `audio.volume` |
|
|
|
|
## Connected Peers
|
|
|
|
```js
|
|
export function activate(context) {
|
|
const peerIds = context.api.p2p.connectedPeers();
|
|
|
|
context.api.logger.info('Connected peers', { peerIds });
|
|
}
|
|
```
|
|
|
|
## Broadcast Data
|
|
|
|
```js
|
|
export function activate(context) {
|
|
context.api.p2p.broadcastData('soundboard:played', {
|
|
soundId: 'airhorn-short',
|
|
label: 'Airhorn',
|
|
playedBy: 'Alice',
|
|
playedAt: 1777473600000
|
|
});
|
|
}
|
|
```
|
|
|
|
## Send Data to One Peer
|
|
|
|
```js
|
|
export function activate(context) {
|
|
context.api.p2p.sendData('peer-muse-laptop', 'private-tool:ping', {
|
|
requestId: 'ping-20260429-001',
|
|
message: 'Are you receiving plugin data?'
|
|
});
|
|
}
|
|
```
|
|
|
|
## Play an Audio Clip
|
|
|
|
```js
|
|
export async function activate(context) {
|
|
await context.api.media.playAudioClip({
|
|
url: 'https://cdn.example.com/metoyou/sounds/chime.wav',
|
|
volume: 0.65
|
|
});
|
|
}
|
|
```
|
|
|
|
## Add a Custom Audio Stream
|
|
|
|
```js
|
|
export async function activate(context) {
|
|
const audioContext = new AudioContext();
|
|
const oscillator = audioContext.createOscillator();
|
|
const gain = audioContext.createGain();
|
|
const destination = audioContext.createMediaStreamDestination();
|
|
|
|
oscillator.type = 'sine';
|
|
oscillator.frequency.value = 440;
|
|
gain.gain.value = 0.03;
|
|
oscillator.connect(gain);
|
|
gain.connect(destination);
|
|
oscillator.start();
|
|
|
|
await context.api.media.addCustomAudioStream({
|
|
label: 'Tuning tone',
|
|
stream: destination.stream
|
|
});
|
|
|
|
setTimeout(async () => {
|
|
oscillator.stop();
|
|
await audioContext.close();
|
|
}, 1000);
|
|
}
|
|
```
|
|
|
|
## Add a Custom Video Stream
|
|
|
|
```js
|
|
export async function activate(context) {
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = 1280;
|
|
canvas.height = 720;
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
ctx.fillStyle = '#111827';
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
ctx.fillStyle = '#ffffff';
|
|
ctx.font = '48px sans-serif';
|
|
ctx.fillText('Plugin camera scene', 80, 120);
|
|
|
|
const stream = canvas.captureStream(15);
|
|
|
|
await context.api.media.addCustomVideoStream({
|
|
label: 'Plugin camera scene',
|
|
stream
|
|
});
|
|
}
|
|
```
|
|
|
|
## Set Volumes
|
|
|
|
```js
|
|
export function activate(context) {
|
|
context.api.media.setInputVolume(0.85);
|
|
context.api.media.setOutputVolume(0.75);
|
|
}
|
|
```
|
|
|
|
Use media APIs with visible controls and clear user consent. Unexpected audio or video is a poor user experience. |