@vidtreo/recorder-vue 1.6.0
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 +412 -0
- package/dist/components/MobileWebRecorderUI.vue.d.ts +7 -0
- package/dist/components/NativeCameraUI.vue.d.ts +7 -0
- package/dist/components/StandardRecorder.vue.d.ts +29 -0
- package/dist/components/VidtreoRecorder.vue.d.ts +29 -0
- package/dist/components/ui/AudioVisualizer.vue.d.ts +7 -0
- package/dist/components/ui/AudioWarningToast.vue.d.ts +35 -0
- package/dist/components/ui/ConfigurationErrorDisplay.vue.d.ts +9 -0
- package/dist/components/ui/DeviceErrorOverlay.vue.d.ts +14 -0
- package/dist/components/ui/DeviceSelector.vue.d.ts +18 -0
- package/dist/components/ui/ErrorBoundary.vue.d.ts +21 -0
- package/dist/components/ui/PermissionFlowSteps.vue.d.ts +40 -0
- package/dist/components/ui/PermissionRecoveryGuide.vue.d.ts +7 -0
- package/dist/components/ui/PreviewContent.vue.d.ts +72 -0
- package/dist/components/ui/RecordingControlsButtons.vue.d.ts +72 -0
- package/dist/components/ui/SettingsPanel.vue.d.ts +34 -0
- package/dist/components/ui/TranscodingProgress.vue.d.ts +6 -0
- package/dist/components/ui/UploadProgress.vue.d.ts +7 -0
- package/dist/components/ui/VideoPreview.vue.d.ts +16 -0
- package/dist/components/ui/VideoPreviewSkeleton.vue.d.ts +8 -0
- package/dist/composables/use-mobile-web-recorder.d.ts +8 -0
- package/dist/composables/use-native-camera.d.ts +22 -0
- package/dist/composables/use-permission-flow.d.ts +22 -0
- package/dist/composables/use-recorder-translations.d.ts +46 -0
- package/dist/composables/use-vidtreo-recorder.d.ts +2 -0
- package/dist/constants/constants.d.ts +1 -0
- package/dist/i18n/translations.d.ts +96 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +1 -0
- package/dist/recorder-vue.css +1 -0
- package/dist/services/config-service-wrapper.d.ts +15 -0
- package/dist/services/upload-service-wrapper.d.ts +12 -0
- package/dist/types/index.d.ts +128 -0
- package/dist/utils/button-visibility.d.ts +18 -0
- package/dist/utils/config-builder.d.ts +4 -0
- package/dist/utils/device-error-overlay-mapper.d.ts +29 -0
- package/dist/utils/download-file.d.ts +1 -0
- package/dist/utils/env-utils.d.ts +1 -0
- package/dist/utils/min-time-record.d.ts +9 -0
- package/dist/utils/recorder-constants.d.ts +12 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
# @vidtreo/recorder-vue
|
|
2
|
+
|
|
3
|
+
Vue 3 components and composables for the Vidtreo video recording SDK. Drop the recorder into any Vue app with a single tag, or build a fully custom UI on top of the same battle-tested composables that power [`@vidtreo/recorder-react`](../recorder-react) โ same recording pipeline, same upload queue, same i18n, native Composition API ergonomics.
|
|
4
|
+
|
|
5
|
+
## What you get out of the box
|
|
6
|
+
|
|
7
|
+
- ๐ฅ **Camera + screen capture** with one-click source switching, mute, pause/resume, and device selection.
|
|
8
|
+
- โฑ๏ธ **Countdown, timer, audio meter, transcoding progress, upload progress** โ all wired and styled.
|
|
9
|
+
- ๐ **Permission flow** with a polished overlay that walks the user through allowing camera + mic, plus a recovery guide when they were denied.
|
|
10
|
+
- ๐ฑ **Mobile-aware** โ overlay modal, embedded mode, or the device's native camera (file input), selectable via the `mobileMode` prop.
|
|
11
|
+
- ๐ **i18n** out of the box (English + Spanish) and full per-string overrides for any language you want.
|
|
12
|
+
- ๐งช **SSR-safe** โ every browser API is gated to client-side mount. Drop it in Nuxt with [`@vidtreo/recorder-nuxt`](../recorder-nuxt) and forget about hydration mismatches.
|
|
13
|
+
- ๐ ๏ธ **Composable API** for building your own UI โ same shape as `@vidtreo/recorder-react`, so React-to-Vue migrations are 1:1.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @vidtreo/recorder-vue @vidtreo/recorder
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Peer dependencies**:
|
|
22
|
+
- `@vidtreo/recorder >=1.6.0`
|
|
23
|
+
- `vue >=3.0.0`
|
|
24
|
+
|
|
25
|
+
Don't forget the stylesheet โ either import it once in your entry, or rely on the built-in CSS injection (added to `<head>` automatically when the package loads).
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// Optional explicit import โ useful if you bundle styles separately
|
|
29
|
+
import "@vidtreo/recorder-vue/styles.css";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
### Drop-in component (2 lines)
|
|
35
|
+
|
|
36
|
+
```vue
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<VidtreoRecorder :recorder-props="{ apiKey: 'your-api-key' }" />
|
|
43
|
+
</template>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Using environment variables
|
|
47
|
+
|
|
48
|
+
For Vite-based apps, expose the key via `import.meta.env`:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# .env
|
|
52
|
+
VITE_VIDTREO_API_KEY=your-api-key
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```vue
|
|
56
|
+
<script setup lang="ts">
|
|
57
|
+
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
|
|
58
|
+
|
|
59
|
+
const apiKey = import.meta.env.VITE_VIDTREO_API_KEY as string;
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<template>
|
|
63
|
+
<VidtreoRecorder :recorder-props="{ apiKey }" />
|
|
64
|
+
</template>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Component API
|
|
68
|
+
|
|
69
|
+
The component accepts a single `recorder-props` object so the discriminated union (`demo: true` vs `apiKey`) stays type-safe at the call site. Events use the standard Vue `@event-name` listener syntax.
|
|
70
|
+
|
|
71
|
+
### Props (`recorder-props`)
|
|
72
|
+
|
|
73
|
+
| Prop | Type | Required | Default | Description |
|
|
74
|
+
|------|------|----------|---------|-------------|
|
|
75
|
+
| `apiKey` | `string` | Yes* | โ | API key for authentication. *Optional when `demo: true`. |
|
|
76
|
+
| `demo` | `boolean` | No | `false` | Demo mode. Skips upload and lets you download the local recording. |
|
|
77
|
+
| `backendUrl` | `string` | No | `https://core.vidtreo.com` | Backend API URL. |
|
|
78
|
+
| `countdownDuration` | `number` | No | โ | Pre-recording countdown (milliseconds). |
|
|
79
|
+
| `minTimeRecord` | `number` | No | โ | Minimum recording time in ms before Stop is allowed (e.g., `10_000`). |
|
|
80
|
+
| `maxRecordingTime` | `number` | No | โ | Maximum recording time in milliseconds. |
|
|
81
|
+
| `userMetadata` | `Record<string, unknown>` | No | โ | Custom metadata attached to uploads. |
|
|
82
|
+
| `enableSourceSwitching` | `boolean` | No | `true` | Toggle between camera and screen. |
|
|
83
|
+
| `enableMute` | `boolean` | No | `true` | Show the mute/unmute button. |
|
|
84
|
+
| `enablePause` | `boolean` | No | `true` | Show pause/resume buttons. |
|
|
85
|
+
| `enableDeviceChange` | `boolean` | No | `true` | Show the settings panel with cam/mic selectors. |
|
|
86
|
+
| `enableTabVisibilityOverlay` | `boolean` | No | `false` | Show overlay when the user switches tabs (camera recordings only). |
|
|
87
|
+
| `tabVisibilityOverlayText` | `string` | No | localized default | Custom message for the tab-visibility overlay. |
|
|
88
|
+
| `mobileMode` | `"embed" \| "overlay" \| "native"` | No | `"overlay"` | Mobile experience. `"embed"` = same as desktop, `"overlay"` = fullscreen modal, `"native"` = device's native camera (file input). |
|
|
89
|
+
| `nativeCamera` | `boolean` | No | โ | **Deprecated** โ use `mobileMode: "native"` instead. |
|
|
90
|
+
| `maxFileSize` | `number` | No | โ | Maximum file size in MB (native camera mode). |
|
|
91
|
+
| `lang` | `string` | No | `"en"` | Language code (`"en"` or `"es"`). |
|
|
92
|
+
| `texts` | `PartialTranslations` | No | โ | Per-key text overrides. |
|
|
93
|
+
|
|
94
|
+
### Events
|
|
95
|
+
|
|
96
|
+
| Event | Payload | Fired when |
|
|
97
|
+
|-------|---------|------------|
|
|
98
|
+
| `recording-start` | โ | Recording begins (after the countdown finishes). |
|
|
99
|
+
| `recording-stop` | โ | Recording ends and processing starts. |
|
|
100
|
+
| `upload-progress` | `progress: number` (0..1) | Each chunk is uploaded. |
|
|
101
|
+
| `upload-complete` | `{ recordingId: string; uploadUrl: string }` | Upload finishes. |
|
|
102
|
+
| `upload-error` | `error: Error` | Upload fails. |
|
|
103
|
+
| `transcoding-progress` | `progress: number` (0..1) | Native-camera transcoding progress. |
|
|
104
|
+
| `error` | `error: Error` | Any unhandled error. |
|
|
105
|
+
|
|
106
|
+
### Example with listeners
|
|
107
|
+
|
|
108
|
+
```vue
|
|
109
|
+
<script setup lang="ts">
|
|
110
|
+
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
|
|
111
|
+
import type { VidtreoRecorderProps } from "@vidtreo/recorder-vue";
|
|
112
|
+
|
|
113
|
+
const recorderProps: VidtreoRecorderProps = {
|
|
114
|
+
apiKey: "your-api-key",
|
|
115
|
+
countdownDuration: 3,
|
|
116
|
+
minTimeRecord: 10_000,
|
|
117
|
+
lang: "en",
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
function onComplete(result: { recordingId: string; uploadUrl: string }) {
|
|
121
|
+
console.log("Recording uploaded:", result.recordingId);
|
|
122
|
+
console.log("View at:", result.uploadUrl);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function onProgress(progress: number) {
|
|
126
|
+
console.log(`Upload: ${Math.round(progress * 100)}%`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function onError(error: Error) {
|
|
130
|
+
console.error("Recorder error:", error.message);
|
|
131
|
+
}
|
|
132
|
+
</script>
|
|
133
|
+
|
|
134
|
+
<template>
|
|
135
|
+
<VidtreoRecorder
|
|
136
|
+
:recorder-props="recorderProps"
|
|
137
|
+
@upload-complete="onComplete"
|
|
138
|
+
@upload-progress="onProgress"
|
|
139
|
+
@error="onError"
|
|
140
|
+
/>
|
|
141
|
+
</template>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Composable API
|
|
145
|
+
|
|
146
|
+
When the default component doesn't fit your UI, drop down to the `useVidtreoRecorder` composable and assemble your own.
|
|
147
|
+
|
|
148
|
+
```vue
|
|
149
|
+
<script setup lang="ts">
|
|
150
|
+
import { useVidtreoRecorder } from "@vidtreo/recorder-vue";
|
|
151
|
+
|
|
152
|
+
const { state, actions, audioLevel, controller } = useVidtreoRecorder({
|
|
153
|
+
apiKey: "your-api-key",
|
|
154
|
+
onUploadComplete: (result) => console.log("Upload complete:", result),
|
|
155
|
+
});
|
|
156
|
+
</script>
|
|
157
|
+
|
|
158
|
+
<template>
|
|
159
|
+
<div>
|
|
160
|
+
<video v-if="state.stream" :srcObject="state.stream" autoplay muted playsinline />
|
|
161
|
+
|
|
162
|
+
<button v-if="state.recordingState === 'idle'" @click="actions.startRecording()">
|
|
163
|
+
Start
|
|
164
|
+
</button>
|
|
165
|
+
<button v-else @click="actions.stopRecording()">
|
|
166
|
+
Stop
|
|
167
|
+
</button>
|
|
168
|
+
|
|
169
|
+
<div>Timer: {{ state.timer }}</div>
|
|
170
|
+
<div>Audio level: {{ audioLevel }}</div>
|
|
171
|
+
<div v-if="state.error" class="error">{{ state.error }}</div>
|
|
172
|
+
</div>
|
|
173
|
+
</template>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### What the composable returns
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
{
|
|
180
|
+
state: Reactive<VidtreoRecorderState>; // mutate freely, fully reactive
|
|
181
|
+
actions: VidtreoRecorderActions; // plain methods
|
|
182
|
+
audioLevel: Ref<number>; // 0..1 โ perfect for waveform UIs
|
|
183
|
+
controller: ShallowRef<RecorderController>; // raw core SDK if you need it
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### `state`
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
{
|
|
191
|
+
recordingState: "idle" | "countdown" | "recording";
|
|
192
|
+
stream: MediaStream | null;
|
|
193
|
+
isMuted: boolean;
|
|
194
|
+
isPaused: boolean;
|
|
195
|
+
isAudioReady: boolean;
|
|
196
|
+
hasAudioFailed: boolean;
|
|
197
|
+
error: string | null;
|
|
198
|
+
errorCode: string | null;
|
|
199
|
+
countdown: number | null;
|
|
200
|
+
timer: string; // "00:12" format
|
|
201
|
+
uploadProgress: number | null; // 0..1 or null
|
|
202
|
+
transitionMessage: string | null;
|
|
203
|
+
isInitialized: boolean;
|
|
204
|
+
recordedBlob: Blob | null; // populated in demo mode
|
|
205
|
+
audioWarning: AudioWarning | null;
|
|
206
|
+
audioRecovered: boolean;
|
|
207
|
+
devices: {
|
|
208
|
+
cameras: MediaDeviceInfo[];
|
|
209
|
+
microphones: MediaDeviceInfo[];
|
|
210
|
+
selectedCamera: string | null;
|
|
211
|
+
selectedMic: string | null;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### `actions`
|
|
217
|
+
|
|
218
|
+
| Action | Signature | What it does |
|
|
219
|
+
|--------|-----------|--------------|
|
|
220
|
+
| `startRecording` | `(sourceType?: "camera" \| "screen") => Promise<void>` | Begin recording (after countdown if configured). |
|
|
221
|
+
| `stopRecording` | `() => Promise<RecordingStopResult>` | Stop and trigger upload. |
|
|
222
|
+
| `pauseRecording` | `() => void` | Pause an active recording. |
|
|
223
|
+
| `resumeRecording` | `() => void` | Resume from pause. |
|
|
224
|
+
| `toggleMute` | `() => void` | Toggle the audio mute state. |
|
|
225
|
+
| `switchSource` | `(sourceType: "camera" \| "screen") => Promise<void>` | Swap between camera and screen during preview/recording. |
|
|
226
|
+
| `changeCamera` | `(deviceId: string) => Promise<void>` | Switch to a different camera. |
|
|
227
|
+
| `changeMic` | `(deviceId: string) => Promise<void>` | Switch to a different microphone. |
|
|
228
|
+
| `startPreview` | `(sourceType?: "camera" \| "screen") => Promise<void>` | Open the stream without recording. |
|
|
229
|
+
| `stopPreview` | `() => void` | Tear the preview stream down. |
|
|
230
|
+
| `downloadVideo` | `() => void` | Download the last `recordedBlob` (demo mode). |
|
|
231
|
+
| `cleanup` | `() => void` | Release all resources. Useful before unmounting. |
|
|
232
|
+
|
|
233
|
+
### Specialized composables
|
|
234
|
+
|
|
235
|
+
| Composable | Purpose |
|
|
236
|
+
|------------|---------|
|
|
237
|
+
| `useMobileWebRecorder(config)` | Wraps `useVidtreoRecorder` and adds `isModalOpen`, `openModal`, `closeModal`, `canCloseModal` for the mobile overlay experience. |
|
|
238
|
+
| `useNativeCamera(config)` | File-input + transcoding flow used when `mobileMode: "native"`. Returns `{ state, actions }` with `handleFileSelect`, `processAndUpload`, `downloadVideo`, `reset`. |
|
|
239
|
+
| `usePermissionFlow(options)` | Drives the camera/mic permission overlay. Returns `{ isActive, isComplete, currentStep, steps, recoveryData, requestPermission, retryPermission }` โ useful if you want to build a fully custom permission UI. |
|
|
240
|
+
| `useRecorderTranslations(translations)` | Splits a `TranslationKeys` object into `preview`, `buttons`, and `settings` subsets as `ComputedRef`s. Accepts `MaybeRefOrGetter<TranslationKeys>` so it stays reactive when the language changes. |
|
|
241
|
+
|
|
242
|
+
## Internationalization
|
|
243
|
+
|
|
244
|
+
Built-in: **English** (`en`) and **Spanish** (`es`). Use the `lang` prop to switch, and `texts` to override individual strings or to ship a brand-new language entirely.
|
|
245
|
+
|
|
246
|
+
### Switch language
|
|
247
|
+
|
|
248
|
+
```vue
|
|
249
|
+
<template>
|
|
250
|
+
<VidtreoRecorder :recorder-props="{ apiKey, lang: 'es' }" />
|
|
251
|
+
</template>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Override individual strings
|
|
255
|
+
|
|
256
|
+
```vue
|
|
257
|
+
<script setup lang="ts">
|
|
258
|
+
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
|
|
259
|
+
|
|
260
|
+
const recorderProps = {
|
|
261
|
+
apiKey: "your-api-key",
|
|
262
|
+
lang: "en",
|
|
263
|
+
texts: {
|
|
264
|
+
record: "๐ด Start Capture",
|
|
265
|
+
stop: "โน๏ธ End Capture",
|
|
266
|
+
settings: "Options",
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
</script>
|
|
270
|
+
|
|
271
|
+
<template>
|
|
272
|
+
<VidtreoRecorder :recorder-props="recorderProps" />
|
|
273
|
+
</template>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Ship a completely custom language (e.g., French)
|
|
277
|
+
|
|
278
|
+
```vue
|
|
279
|
+
<script setup lang="ts">
|
|
280
|
+
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
|
|
281
|
+
import type { PartialTranslations } from "@vidtreo/recorder-vue";
|
|
282
|
+
|
|
283
|
+
const french: PartialTranslations = {
|
|
284
|
+
initializingCamera: "Initialisation de la camรฉra...",
|
|
285
|
+
grantPermissions: "Accordez les autorisations de camรฉra et de microphone",
|
|
286
|
+
switchingDevice: "Changement d'appareil...",
|
|
287
|
+
recordingStartsIn: "L'enregistrement commence dans...",
|
|
288
|
+
switchingSource: "Changement de source...",
|
|
289
|
+
rec: "ENREG",
|
|
290
|
+
settings: "Paramรจtres",
|
|
291
|
+
record: "Enregistrer",
|
|
292
|
+
stop: "Arrรชter",
|
|
293
|
+
pause: "Pause",
|
|
294
|
+
resume: "Reprendre",
|
|
295
|
+
mute: "Muet",
|
|
296
|
+
unmute: "Activer le son",
|
|
297
|
+
switchSource: "Changer de source",
|
|
298
|
+
camera: "Camรฉra",
|
|
299
|
+
microphone: "Microphone",
|
|
300
|
+
uploading: "Tรฉlรฉchargement...",
|
|
301
|
+
};
|
|
302
|
+
</script>
|
|
303
|
+
|
|
304
|
+
<template>
|
|
305
|
+
<VidtreoRecorder
|
|
306
|
+
:recorder-props="{ apiKey: 'your-api-key', lang: 'fr', texts: french }"
|
|
307
|
+
/>
|
|
308
|
+
</template>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Dynamic language switching
|
|
312
|
+
|
|
313
|
+
The component is fully reactive โ change `lang` and the UI re-localizes without a remount:
|
|
314
|
+
|
|
315
|
+
```vue
|
|
316
|
+
<script setup lang="ts">
|
|
317
|
+
import { ref } from "vue";
|
|
318
|
+
import { VidtreoRecorder } from "@vidtreo/recorder-vue";
|
|
319
|
+
|
|
320
|
+
const language = ref<"en" | "es">("en");
|
|
321
|
+
</script>
|
|
322
|
+
|
|
323
|
+
<template>
|
|
324
|
+
<select v-model="language">
|
|
325
|
+
<option value="en">English</option>
|
|
326
|
+
<option value="es">Espaรฑol</option>
|
|
327
|
+
</select>
|
|
328
|
+
|
|
329
|
+
<VidtreoRecorder :recorder-props="{ apiKey: 'your-api-key', lang: language }" />
|
|
330
|
+
</template>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Translation keys
|
|
334
|
+
|
|
335
|
+
| Key | English | Spanish |
|
|
336
|
+
|-----|---------|---------|
|
|
337
|
+
| `initializingCamera` | Initializing camera... | Inicializando cรกmara... |
|
|
338
|
+
| `grantPermissions` | Grant camera and microphone permissions when prompted | Otorga permisos de cรกmara y micrรณfono cuando se solicite |
|
|
339
|
+
| `switchingDevice` | Switching device... | Cambiando dispositivo... |
|
|
340
|
+
| `recordingStartsIn` | Recording starts in... | La grabaciรณn comienza en... |
|
|
341
|
+
| `switchingSource` | Switching source... | Cambiando fuente... |
|
|
342
|
+
| `rec` | REC | GRAB |
|
|
343
|
+
| `settings` | Settings | Configuraciรณn |
|
|
344
|
+
| `record` | Record | Grabar |
|
|
345
|
+
| `stop` | Stop | Detener |
|
|
346
|
+
| `minimumRecordingTimeNotReached` | You have not met the minimum recording time yet | Aun no cumples el tiempo minimo de grabacion |
|
|
347
|
+
| `pause` | Pause | Pausar |
|
|
348
|
+
| `resume` | Resume | Reanudar |
|
|
349
|
+
| `mute` | Mute | Silenciar |
|
|
350
|
+
| `unmute` | Unmute | Activar sonido |
|
|
351
|
+
| `switchSource` | Switch Source | Cambiar Fuente |
|
|
352
|
+
| `camera` | Camera | Cรกmara |
|
|
353
|
+
| `microphone` | Microphone | Micrรณfono |
|
|
354
|
+
| `uploading` | Uploading... | Subiendo... |
|
|
355
|
+
|
|
356
|
+
The full key list lives in [`src/i18n/translations.ts`](./src/i18n/translations.ts) โ there's a key for every visible string, including the permission flow recovery guide.
|
|
357
|
+
|
|
358
|
+
## Mobile experience
|
|
359
|
+
|
|
360
|
+
`mobileMode` controls how the recorder behaves on mobile devices:
|
|
361
|
+
|
|
362
|
+
| Value | Behavior |
|
|
363
|
+
|-------|----------|
|
|
364
|
+
| `"overlay"` (default) | A landing screen with "Allow Access". On tap, a fullscreen modal opens (via `<Teleport>`) with the same UI as desktop. |
|
|
365
|
+
| `"embed"` | The recorder embeds inline, identical to desktop. |
|
|
366
|
+
| `"native"` | Skips the SDK UI entirely and opens the device's native camera via a file input. Useful when WebCodecs isn't reliable on the user's browser. |
|
|
367
|
+
|
|
368
|
+
The `<VidtreoRecorder>` component probes browser capabilities on mobile and falls back gracefully when `WebCodecs` isn't available.
|
|
369
|
+
|
|
370
|
+
## SSR (Nuxt, Astro-Vue, etc.)
|
|
371
|
+
|
|
372
|
+
Every browser API is gated to `onMounted`/`if (typeof window !== "undefined")`. If you're on Nuxt 3, the cleanest path is the [`@vidtreo/recorder-nuxt`](../recorder-nuxt) module โ it registers the component as `client`-only and injects the CSS for you.
|
|
373
|
+
|
|
374
|
+
For other SSR setups, wrap the component in `<ClientOnly>` (Nuxt) or guard it behind a mount check in your framework's equivalent.
|
|
375
|
+
|
|
376
|
+
## TypeScript
|
|
377
|
+
|
|
378
|
+
Every public surface is typed. Import types directly:
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
import type {
|
|
382
|
+
VidtreoRecorderProps,
|
|
383
|
+
VidtreoRecorderState,
|
|
384
|
+
VidtreoRecorderActions,
|
|
385
|
+
UseVidtreoRecorderConfig,
|
|
386
|
+
UseVidtreoRecorderReturn,
|
|
387
|
+
PartialTranslations,
|
|
388
|
+
TranslationKeys,
|
|
389
|
+
MobileMode,
|
|
390
|
+
AudioWarning,
|
|
391
|
+
RecordingStopResult,
|
|
392
|
+
} from "@vidtreo/recorder-vue";
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Package structure
|
|
396
|
+
|
|
397
|
+
| What | Where |
|
|
398
|
+
|------|-------|
|
|
399
|
+
| Top-level component | `src/components/VidtreoRecorder.vue` |
|
|
400
|
+
| Desktop / embed UI | `src/components/StandardRecorder.vue` |
|
|
401
|
+
| Mobile overlay | `src/components/MobileWebRecorderUI.vue` |
|
|
402
|
+
| Native camera | `src/components/NativeCameraUI.vue` |
|
|
403
|
+
| Composables | `src/composables/` |
|
|
404
|
+
| UI primitives | `src/components/ui/` |
|
|
405
|
+
| i18n data | `src/i18n/translations.ts` |
|
|
406
|
+
| Framework-agnostic helpers | `src/utils/`, `src/services/` |
|
|
407
|
+
|
|
408
|
+
The recording engine, transcoding worker, and upload pipeline live in [`@vidtreo/recorder`](../recorder).
|
|
409
|
+
|
|
410
|
+
## License
|
|
411
|
+
|
|
412
|
+
MIT
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UseVidtreoRecorderConfig } from "../types";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
config: UseVidtreoRecorderConfig;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
|
+
declare const _default: typeof __VLS_export;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UseVidtreoRecorderConfig } from "../types";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
config: UseVidtreoRecorderConfig;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
|
+
declare const _default: typeof __VLS_export;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { VidtreoRecorderProps } from "../types";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
recorderProps: VidtreoRecorderProps;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
error: (error: Error) => any;
|
|
7
|
+
uploadProgress: (progress: number) => any;
|
|
8
|
+
transcodingProgress: (progress: number) => any;
|
|
9
|
+
recordingStart: () => any;
|
|
10
|
+
recordingStop: () => any;
|
|
11
|
+
uploadComplete: (result: {
|
|
12
|
+
recordingId: string;
|
|
13
|
+
uploadUrl: string;
|
|
14
|
+
}) => any;
|
|
15
|
+
uploadError: (error: Error) => any;
|
|
16
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
|
+
onError?: ((error: Error) => any) | undefined;
|
|
18
|
+
onUploadProgress?: ((progress: number) => any) | undefined;
|
|
19
|
+
onTranscodingProgress?: ((progress: number) => any) | undefined;
|
|
20
|
+
onRecordingStart?: (() => any) | undefined;
|
|
21
|
+
onRecordingStop?: (() => any) | undefined;
|
|
22
|
+
onUploadComplete?: ((result: {
|
|
23
|
+
recordingId: string;
|
|
24
|
+
uploadUrl: string;
|
|
25
|
+
}) => any) | undefined;
|
|
26
|
+
onUploadError?: ((error: Error) => any) | undefined;
|
|
27
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
|
+
declare const _default: typeof __VLS_export;
|
|
29
|
+
export default _default;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { VidtreoRecorderProps } from "../types";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
recorderProps: VidtreoRecorderProps;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
error: (error: Error) => any;
|
|
7
|
+
uploadProgress: (progress: number) => any;
|
|
8
|
+
transcodingProgress: (progress: number) => any;
|
|
9
|
+
recordingStart: () => any;
|
|
10
|
+
recordingStop: () => any;
|
|
11
|
+
uploadComplete: (result: {
|
|
12
|
+
recordingId: string;
|
|
13
|
+
uploadUrl: string;
|
|
14
|
+
}) => any;
|
|
15
|
+
uploadError: (error: Error) => any;
|
|
16
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
|
+
onError?: ((error: Error) => any) | undefined;
|
|
18
|
+
onUploadProgress?: ((progress: number) => any) | undefined;
|
|
19
|
+
onTranscodingProgress?: ((progress: number) => any) | undefined;
|
|
20
|
+
onRecordingStart?: (() => any) | undefined;
|
|
21
|
+
onRecordingStop?: (() => any) | undefined;
|
|
22
|
+
onUploadComplete?: ((result: {
|
|
23
|
+
recordingId: string;
|
|
24
|
+
uploadUrl: string;
|
|
25
|
+
}) => any) | undefined;
|
|
26
|
+
onUploadError?: ((error: Error) => any) | undefined;
|
|
27
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
|
+
declare const _default: typeof __VLS_export;
|
|
29
|
+
export default _default;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
audioLevel: number;
|
|
3
|
+
isMuted: boolean;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
|
+
declare const _default: typeof __VLS_export;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AudioWarning } from "@vidtreo/recorder";
|
|
2
|
+
export type AudioWarningSeverity = "critical" | "soft";
|
|
3
|
+
export type AudioWarningCopy = {
|
|
4
|
+
title: string;
|
|
5
|
+
message: string;
|
|
6
|
+
dismissLabel: string;
|
|
7
|
+
};
|
|
8
|
+
export type AudioWarningToastTranslations = {
|
|
9
|
+
audioWarningNoSignalTitle: string;
|
|
10
|
+
audioWarningNoSignalMessage: string;
|
|
11
|
+
audioWarningLowSignalTitle: string;
|
|
12
|
+
audioWarningLowSignalMessage: string;
|
|
13
|
+
audioWarningTrackEndedTitle: string;
|
|
14
|
+
audioWarningTrackEndedMessage: string;
|
|
15
|
+
audioWarningNoChunksTitle: string;
|
|
16
|
+
audioWarningNoChunksMessage: string;
|
|
17
|
+
audioWarningTrackMutedTitle: string;
|
|
18
|
+
audioWarningTrackMutedMessage: string;
|
|
19
|
+
audioWarningDismiss: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function getAudioWarningSeverity(code: AudioWarning["code"]): AudioWarningSeverity;
|
|
22
|
+
export declare function resolveAudioWarningCopy(code: AudioWarning["code"], translations: AudioWarningToastTranslations): AudioWarningCopy;
|
|
23
|
+
declare const _default: typeof __VLS_export;
|
|
24
|
+
export default _default;
|
|
25
|
+
declare const __VLS_export: import("vue").DefineComponent<{
|
|
26
|
+
warning: AudioWarning | null;
|
|
27
|
+
translations: AudioWarningToastTranslations;
|
|
28
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
29
|
+
dismiss: () => any;
|
|
30
|
+
}, string, import("vue").PublicProps, Readonly<{
|
|
31
|
+
warning: AudioWarning | null;
|
|
32
|
+
translations: AudioWarningToastTranslations;
|
|
33
|
+
}> & Readonly<{
|
|
34
|
+
onDismiss?: (() => any) | undefined;
|
|
35
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type PartialTranslations } from "../../i18n/translations";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
error: Error | null;
|
|
4
|
+
lang?: string;
|
|
5
|
+
texts?: PartialTranslations;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
visible: boolean;
|
|
3
|
+
variant: "camera" | "audio" | "browser" | "generic";
|
|
4
|
+
title: string;
|
|
5
|
+
message: string;
|
|
6
|
+
retryLabel?: string;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
retry: () => any;
|
|
10
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
11
|
+
onRetry?: (() => any) | undefined;
|
|
12
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type DeviceProps = {
|
|
2
|
+
devices: {
|
|
3
|
+
cameras: MediaDeviceInfo[];
|
|
4
|
+
microphones: MediaDeviceInfo[];
|
|
5
|
+
selectedCamera: string | null;
|
|
6
|
+
selectedMic: string | null;
|
|
7
|
+
};
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_export: import("vue").DefineComponent<DeviceProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
+
cameraChange: (deviceId: string) => any;
|
|
12
|
+
micChange: (deviceId: string) => any;
|
|
13
|
+
}, string, import("vue").PublicProps, Readonly<DeviceProps> & Readonly<{
|
|
14
|
+
onCameraChange?: ((deviceId: string) => any) | undefined;
|
|
15
|
+
onMicChange?: ((deviceId: string) => any) | undefined;
|
|
16
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PartialTranslations } from "../../i18n/translations";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
variant?: "preview" | "recorder";
|
|
4
|
+
lang?: string;
|
|
5
|
+
texts?: PartialTranslations;
|
|
6
|
+
};
|
|
7
|
+
declare var __VLS_11: {};
|
|
8
|
+
type __VLS_Slots = {} & {
|
|
9
|
+
default?: (props: typeof __VLS_11) => any;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
12
|
+
variant: "preview" | "recorder";
|
|
13
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
17
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
18
|
+
new (): {
|
|
19
|
+
$slots: S;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { PermissionFlowState, PermissionFlowStep } from "@vidtreo/recorder";
|
|
2
|
+
import type { PermissionFlowStepInfo } from "../../composables/use-permission-flow";
|
|
3
|
+
export type PermissionFlowStepsTranslations = {
|
|
4
|
+
title: string;
|
|
5
|
+
cameraTitle: string;
|
|
6
|
+
microphoneTitle: string;
|
|
7
|
+
cameraLabel: string;
|
|
8
|
+
microphoneLabel: string;
|
|
9
|
+
statusPending: string;
|
|
10
|
+
statusGranted: string;
|
|
11
|
+
statusDenied: string;
|
|
12
|
+
statusRequesting: string;
|
|
13
|
+
allowCamera: string;
|
|
14
|
+
allowMicrophone: string;
|
|
15
|
+
retry: string;
|
|
16
|
+
recoveryTitle: string;
|
|
17
|
+
recoveryInstructions: string;
|
|
18
|
+
recoveryGuideHint: string;
|
|
19
|
+
cameraName: string;
|
|
20
|
+
microphoneName: string;
|
|
21
|
+
connecting: string;
|
|
22
|
+
};
|
|
23
|
+
type __VLS_Props = {
|
|
24
|
+
isActive: boolean;
|
|
25
|
+
isFadingOut: boolean;
|
|
26
|
+
currentStep: PermissionFlowStep;
|
|
27
|
+
steps: readonly PermissionFlowStepInfo[];
|
|
28
|
+
recoveryData: PermissionFlowState["recoveryData"] | undefined;
|
|
29
|
+
canRetry: boolean;
|
|
30
|
+
translations: PermissionFlowStepsTranslations;
|
|
31
|
+
};
|
|
32
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
33
|
+
requestPermission: () => any;
|
|
34
|
+
retryPermission: () => any;
|
|
35
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
36
|
+
onRequestPermission?: (() => any) | undefined;
|
|
37
|
+
onRetryPermission?: (() => any) | undefined;
|
|
38
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
39
|
+
declare const _default: typeof __VLS_export;
|
|
40
|
+
export default _default;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
cameraLabel: string;
|
|
3
|
+
microphoneLabel: string;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
|
+
declare const _default: typeof __VLS_export;
|
|
7
|
+
export default _default;
|