@vanillaskyai/video 0.10.5 → 0.10.6
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/CHANGELOG.md +6 -0
- package/dist/react.js +9 -0
- package/docs/development.md +1 -1
- package/package.json +1 -1
- package/starters/video-chat/package.json +1 -1
- package/starters/video-chat/stock.ts +12 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ VanillaSky follows semantic versioning. This changelog begins with the 0.1 beta.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.10.6
|
|
8
|
+
|
|
9
|
+
- Initialize the reusable narration audio element during the existing user gesture so delayed first speech can play on Safari.
|
|
10
|
+
|
|
11
|
+
- Accept valid Pexels search results without descriptive URL slugs. Rank available matching metadata above unknown relevance, without requiring most query words to appear in the slug.
|
|
12
|
+
|
|
7
13
|
## 0.10.5
|
|
8
14
|
|
|
9
15
|
- Keep footage visible when native playback reports waiting without another playing event. Observe resumed motion directly and recover to the authored chapter after one second without progress, preserving narration.
|
package/dist/react.js
CHANGED
|
@@ -1537,6 +1537,7 @@ async function prepareSceneMedia(variables, signal) {
|
|
|
1537
1537
|
var DEFAULT_MAX_CACHED_LINES = 60;
|
|
1538
1538
|
var SPEECH_PREPARATION_TIMEOUT_MS = 3e3;
|
|
1539
1539
|
var FALLBACK_BITS_PER_SECOND = 128e3;
|
|
1540
|
+
var ACTIVATION_AUDIO = "data:audio/wav;base64,UklGRrQBAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YZABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
|
1540
1541
|
var sharedContext;
|
|
1541
1542
|
function actionEndpoint(endpoint, action) {
|
|
1542
1543
|
const value = String(endpoint);
|
|
@@ -1689,6 +1690,14 @@ function createVideoChatVoice(options = {}) {
|
|
|
1689
1690
|
},
|
|
1690
1691
|
resume() {
|
|
1691
1692
|
held = false;
|
|
1693
|
+
if (!disposed && !silent && !generatedElement && globalThis.navigator?.userActivation?.isActive) {
|
|
1694
|
+
const element = generatedElement = new Audio();
|
|
1695
|
+
element.src = ACTIVATION_AUDIO;
|
|
1696
|
+
try {
|
|
1697
|
+
void element.play().catch(() => void 0);
|
|
1698
|
+
} catch {
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1692
1701
|
if (sounding) {
|
|
1693
1702
|
const fail = playbackFailure;
|
|
1694
1703
|
void sounding.play().catch(() => {
|
package/docs/development.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Run `npm ci --no-audit`, then `npm run dev:chat`. The localhost HMR surface renders the actual SDK `VideoChat`, templates and server handler from source. It never loads provider credentials. Select an intent and fault condition in the development toolbar; use the chat's normal media-mode controls. The prompt box remains the real product UI.
|
|
4
4
|
|
|
5
|
-
Offline answers are deterministic for explanation, story, comedy, imagination, practical steps and golf. They use local waterfall footage and
|
|
5
|
+
Offline answers are deterministic for explanation, story, comedy, imagination, practical steps and golf. They use local waterfall footage and locally synthesized speech matching each displayed opening, body and ending. This harness lets you hear complete narration while checking loading, timing, controls and recovery without AI credits. The waterfall remains generic fixture footage; it cannot prove generated answer quality or visual relevance. See [spoken fixture provenance](https://github.com/VanillaSkyAi/video/blob/main/dev/chat/speech/README.md) for transcripts and regeneration commands. Conditions cover ready, delayed footage, missing media, decode failure, speech failure, exhausted video allowance and request throttling. Browser speech may be used in the speech-failure condition.
|
|
6
6
|
|
|
7
7
|
The toolbar labels source and fixture identity. It separates the first body surface from the first decoded moving-footage frame; the former is a renderer paint opportunity and can precede decode. Its bounded safe phase log records browser request/stream arrival phases, speech response completion, first speech, footage and buffer pauses. No prompts, narration, scene IDs or provider bodies are retained. Media start/end/skip reasons come from the handler’s separate host-only `onDiagnostic` callback, shown in the local terminal for offline fixtures; live hosts own that callback themselves. Stream arrival is not the server’s exact authorship timestamp. Local fixtures never fetch external footage or invoke a paid model. Mode boundaries, provider deadlines and host admission remain covered by their dedicated server and host suites.
|
|
8
8
|
|
package/package.json
CHANGED
|
@@ -8,6 +8,8 @@ interface StockVideo {
|
|
|
8
8
|
interface PexelsVideo {
|
|
9
9
|
url?: string;
|
|
10
10
|
image?: string;
|
|
11
|
+
title?: unknown;
|
|
12
|
+
tags?: unknown;
|
|
11
13
|
video_files?: { link?: string; width?: number; height?: number; file_type?: string }[];
|
|
12
14
|
}
|
|
13
15
|
const cache = new Map<string, { expires: number; media: StockVideo | null }>();
|
|
@@ -21,7 +23,7 @@ function pexelsUrl(value: unknown): value is string {
|
|
|
21
23
|
} catch { return false; }
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
/** Full catalog search.
|
|
26
|
+
/** Full catalog search. Available metadata ranks subject relevance, not factual proof.
|
|
25
27
|
* Applications using this adapter must display a prominent link to Pexels.
|
|
26
28
|
* https://www.pexels.com/api/documentation/#guidelines
|
|
27
29
|
*/
|
|
@@ -41,13 +43,18 @@ export async function findStockFootage(query: string, orientation: VideoOrientat
|
|
|
41
43
|
if (!response.ok) return null;
|
|
42
44
|
const result = await response.json() as { videos?: PexelsVideo[] };
|
|
43
45
|
signal.throwIfAborted();
|
|
44
|
-
let selected: StockVideo | null = null, bestScore =
|
|
46
|
+
let selected: StockVideo | null = null, bestScore = -1;
|
|
45
47
|
for (const video of (Array.isArray(result.videos) ? result.videos : []).slice(0, 12)) {
|
|
46
48
|
if (!pexelsUrl(video.url)) continue;
|
|
47
|
-
const
|
|
49
|
+
const slug = new URL(video.url).pathname.replace(/^\/video\//, "");
|
|
50
|
+
const title = typeof video.title === "string" ? video.title : "";
|
|
51
|
+
const tags = Array.isArray(video.tags) ? video.tags.filter((tag): tag is string => typeof tag === "string").join(" ") : "";
|
|
52
|
+
const subject = words(`${slug} ${title} ${tags}`).filter(token => !/^\d+$/.test(token));
|
|
48
53
|
const matches = tokens.filter(token => subject.includes(token)).length;
|
|
49
|
-
//
|
|
50
|
-
|
|
54
|
+
// The documented Video resource can have only a numeric page URL and no
|
|
55
|
+
// editorial metadata. Preserve provider search order for unknown relevance;
|
|
56
|
+
// positive overlap ranks above it, while explicitly unrelated copy is skipped.
|
|
57
|
+
if (subject.length > 0 && matches === 0) continue;
|
|
51
58
|
const files = (Array.isArray(video.video_files) ? video.video_files : []).filter(file =>
|
|
52
59
|
file.file_type === "video/mp4" && pexelsUrl(file.link)
|
|
53
60
|
&& Number.isFinite(file.width) && Number.isFinite(file.height)
|