@vylt/diplomat
v1.0.0
Published
Real-time AI translation captions for any livestream
Maintainers
Readme
@vylt/diplomat
Real-time AI translation captions for any livestream. Add multilingual captions to your video content in under 5 minutes.
Installation
npm install @vylt/diplomatOr via CDN:
<script src="https://vylt.live/sdk/diplomat/v1/diplomat.min.js"></script>Quick Start
Script Tag (Simplest)
<video id="my-video" src="your-video.mp4"></video>
<div id="diplomat-captions" data-key="dk_live_xxx" data-target-langs="es,fr,de"></div>
<script src="https://vylt.live/sdk/diplomat/v1/diplomat.min.js"></script>React
import { useDiplomat } from '@vylt/diplomat/react';
function VideoPlayer() {
const videoRef = useRef<HTMLVideoElement>(null);
const { captions, currentLang, setLang, isConnected } = useDiplomat({
apiKey: 'dk_live_xxx',
targetLangs: ['es', 'fr', 'de'],
mediaRef: videoRef,
});
return (
<div>
<video ref={videoRef} src="your-video.mp4" />
<select value={currentLang} onChange={(e) => setLang(e.target.value)}>
<option value="es">Spanish</option>
<option value="fr">French</option>
<option value="de">German</option>
</select>
<div className="captions">
{captions.map((c) => <p key={c.id}>{c.translatedText}</p>)}
</div>
</div>
);
}Vue 3
<script setup lang="ts">
import { ref } from 'vue';
import { useDiplomat } from '@vylt/diplomat/vue';
const videoRef = ref<HTMLVideoElement | null>(null);
const { captions, currentLang, setLang, isConnected } = useDiplomat({
apiKey: 'dk_live_xxx',
targetLangs: ['es', 'fr', 'de'],
mediaRef: videoRef,
});
</script>
<template>
<video ref="videoRef" src="your-video.mp4" />
<select :value="currentLang" @change="setLang($event.target.value)">
<option value="es">Spanish</option>
<option value="fr">French</option>
<option value="de">German</option>
</select>
<div class="captions">
<p v-for="caption in captions" :key="caption.id">{{ caption.translatedText }}</p>
</div>
</template>Vanilla JavaScript
const diplomat = Diplomat.create({
apiKey: 'dk_live_xxx',
targetLangs: ['es', 'fr', 'de'],
});
diplomat
.attach(document.getElementById('my-video'))
.on('translation', (caption) => console.log(caption.translatedText))
.setLang('es');Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiKey | string | Required | Your Diplomat API key (starts with dk_) |
| targetLangs | string[] | ['es'] | Languages to translate into |
| sourceLang | string | 'en' | Source language of the audio |
| theme | 'dark' \| 'light' \| 'transparent' | 'dark' | Caption overlay theme |
| position | 'top' \| 'bottom' \| 'custom' | 'bottom' | Caption position |
| fontSize | number | 18 | Caption font size in pixels |
| showBranding | boolean | true | Show "Powered by Diplomat" |
| container | string \| HTMLElement | Auto | Container for captions |
| wsUrl | string | Production URL | WebSocket URL (for testing) |
Events
| Event | Payload | Description |
|-------|---------|-------------|
| translation | CaptionEvent | New caption received |
| error | DiplomatError | Error occurred |
| connect | - | Connected to translation service |
| disconnect | - | Disconnected from service |
| audioStart | - | Audio capture started |
| audioBlocked | - | Browser blocked audio capture |
| langChange | string | Target language changed |
CaptionEvent Object
interface CaptionEvent {
id: string;
originalText: string; // Original transcribed text
translatedText: string; // Translated text
lang: string; // Target language code
timestamp: number; // Unix timestamp
isFinal: boolean; // Whether caption is finalized
confidence?: number; // Transcription confidence (0-1)
}Supported Languages
| Code | Language | Code | Language |
|------|----------|------|----------|
| en | English | ja | Japanese |
| es | Spanish | ko | Korean |
| fr | French | zh | Chinese (Simplified) |
| de | German | zh-TW | Chinese (Traditional) |
| it | Italian | ar | Arabic |
| pt | Portuguese | hi | Hindi |
| nl | Dutch | ru | Russian |
| pl | Polish | tr | Turkish |
| sv | Swedish | vi | Vietnamese |
| da | Danish | th | Thai |
| no | Norwegian | id | Indonesian |
| fi | Finnish | ms | Malay |
| cs | Czech | el | Greek |
| ro | Romanian | he | Hebrew |
| hu | Hungarian | uk | Ukrainian |
React API Reference
useDiplomat Hook
import { useDiplomat } from '@vylt/diplomat/react';
const {
captions, // CaptionEvent[] - Caption history
latestCaption, // CaptionEvent | null - Most recent caption
currentLang, // string - Current target language
availableLangs, // string[] - Available languages
isConnected, // boolean - WebSocket connected
isCapturing, // boolean - Audio being captured
isAudioBlocked, // boolean - Browser blocked audio
isReady, // boolean - SDK loaded (SSR-safe)
error, // DiplomatError | null - Current error
setLang, // (lang: string) => void - Change language
attach, // (element: HTMLMediaElement) => void
enableAudio, // () => void - Resume after block
destroy, // () => void - Cleanup
client, // DiplomatClient | null - Underlying client
} = useDiplomat(options);DiplomatCaptions Component
import { DiplomatCaptions } from '@vylt/diplomat/react';
// Basic usage (uses built-in overlay)
<DiplomatCaptions
apiKey="dk_live_xxx"
targetLangs={['es', 'fr']}
mediaRef={videoRef}
/>
// With render prop for custom UI
<DiplomatCaptions
apiKey="dk_live_xxx"
targetLangs={['es', 'fr']}
mediaRef={videoRef}
>
{({ captions, latestCaption, currentLang, setLang }) => (
<div className="my-captions">
{latestCaption && <p>{latestCaption.translatedText}</p>}
</div>
)}
</DiplomatCaptions>Vue API Reference
useDiplomat Composable
import { useDiplomat } from '@vylt/diplomat/vue';
const {
captions, // Ref<CaptionEvent[]>
latestCaption, // Ref<CaptionEvent | null>
currentLang, // Ref<string>
availableLangs, // Ref<string[]>
isConnected, // Ref<boolean>
isCapturing, // Ref<boolean>
isAudioBlocked, // Ref<boolean>
isReady, // Ref<boolean>
error, // Ref<DiplomatError | null>
setLang, // (lang: string) => void
attach, // (element: HTMLMediaElement) => void
enableAudio, // () => void
destroy, // () => void
client, // Ref<DiplomatClient | null>
} = useDiplomat(options);Global API Reference (Vanilla JS)
// Create instance with chainable API
const diplomat = Diplomat.create(config);
// Methods (all chainable)
diplomat.attach(element | selector);
diplomat.setLang('es');
diplomat.on('translation', callback);
diplomat.off('translation', callback);
// Read-only methods
diplomat.getLang(); // Current language
diplomat.getLangs(); // Available languages
diplomat.isConnected(); // Connection status
diplomat.isCapturing(); // Audio capture status
diplomat.getCaptions(); // Caption history
diplomat.getLatestCaption(); // Latest caption
// Cleanup
diplomat.destroy();
// Static properties
Diplomat.version; // SDK version
Diplomat.supportedLanguages; // Language code -> name map
Diplomat.getInstances(); // All active instances
Diplomat.destroyAll(); // Destroy all instances
// Direct client access (advanced)
const client = new Diplomat.Client(config);Theming
Built-in Themes
// Dark theme (default) - Dark background, white text
Diplomat.create({ theme: 'dark', ... });
// Light theme - Light background, dark text
Diplomat.create({ theme: 'light', ... });
// Transparent - No background, text with shadow
Diplomat.create({ theme: 'transparent', ... });Custom Positioning
Diplomat.create({
position: 'custom',
container: document.getElementById('my-caption-container'),
...
});CSS Customization
.diplomat-overlay {
/* Override default styles */
}
.diplomat-caption {
font-family: 'Your Font', sans-serif;
font-size: 20px;
}
.diplomat-caption--final {
/* Styles for finalized captions */
}Browser Support
- Chrome 80+
- Firefox 78+
- Safari 14+
- Edge 80+
Requires Web Audio API and WebSocket support.
Full Documentation
For complete documentation, examples, and API reference:
vylt.live/developers/diplomat/docs
Get Your API Key
Sign up at vylt.live/developers/diplomat to get your API key.
Support
- Documentation: https://vylt.live/developers/diplomat/docs
- Dashboard: https://vylt.live/admin/tools/diplomat
- Email: [email protected]
License
MIT
Built by VYLT - Sovereignty infrastructure for creators.
