@appvideostudio/sdk
v0.1.4
Published
SDK for building, validating, and previewing AppVideoStudio video compositions
Maintainers
Readme
@appvideostudio/sdk
SDK for building, validating, and previewing AppVideoStudio video compositions.
Install
npm install @appvideostudio/sdkQuick Start
Create a video document
import {
createEmptyVideoDocument,
validateVideoDocument,
} from '@appvideostudio/sdk';
const doc = createEmptyVideoDocument({
name: 'My Video',
width: 1080,
height: 1920,
timelineDuration: 10,
});
doc.timeline.push({
id: 'comp-1',
componentType: 'text-basic',
layerId: 'layer-1',
startTime: 0,
duration: 5,
params: { text: 'Hello world' },
assetBindings: {},
customLabel: null,
color: '#6366f1',
});
const errors = validateVideoDocument(doc);
console.log(errors); // []Embed the player (browser)
import {
AVSPlayerElement,
defineAVSPlayerElement,
} from '@appvideostudio/sdk/player';
defineAVSPlayerElement();
const player = document.createElement('avs-player');
document.body.appendChild(player);
await player.ready;
await player.load(doc);
await player.play();Note: The
<avs-player>element creates an iframe to the AppVideoStudio player runtime athttps://create.appvideostudio.com. The hosted runtime must be reachable for playback to work.
Test with Playwright
import { test } from '@playwright/test';
import { createPlayerHarness } from '@appvideostudio/sdk/test-harness';
import { createEmptyVideoDocument } from '@appvideostudio/sdk';
test('screenshot at 2s', async ({ page }) => {
const doc = createEmptyVideoDocument({ name: 'Test' });
doc.timeline.push({
id: 'comp-1',
componentType: 'text-basic',
layerId: 'layer-1',
startTime: 0,
duration: 5,
params: { text: 'Hello' },
assetBindings: {},
customLabel: null,
color: '#6366f1',
});
const harness = await createPlayerHarness(page, { document: doc });
const screenshot = await harness.screenshotAt(2);
// assert on screenshot buffer
await harness.destroy();
});Note: The test harness requires
@playwright/testas a peer dependency (>=1.40.0).
Entry Points
| Import | Environment | Description |
|---|---|---|
| @appvideostudio/sdk | Node + Browser | Document helpers |
| @appvideostudio/sdk/document | Node + Browser | Document module directly |
| @appvideostudio/sdk/player | Browser only | <avs-player> web component |
| @appvideostudio/sdk/test-harness | Node (Playwright) | Test automation |
Document Model
VideoDocument shape
{
"schemaVersion": 1,
"metadata": { "id": null, "name": "My Video" },
"projectDimensions": { "width": 1080, "height": 1920 },
"timelineDuration": 24,
"layers": [
{ "id": "layer-1", "name": "Layer 1", "color": "#2563eb" }
],
"assets": [
{
"id": "asset-1",
"type": "image",
"name": "Background",
"url": "https://example.com/bg.png",
"posterUrl": null,
"duration": null,
"width": 1080,
"height": 1920,
"mimeType": "image/png"
}
],
"timeline": [
{
"id": "comp-1",
"componentType": "text-basic",
"layerId": "layer-1",
"startTime": 0,
"duration": 5,
"params": { "text": "Hello world" },
"assetBindings": {},
"customLabel": null,
"color": "#6366f1"
}
]
}API Reference
Document Functions
createEmptyVideoDocument(options?)
Create a new empty video document with default layers.
| Option | Type | Default |
|---|---|---|
| id | string | null |
| name | string | "Untitled video" |
| width | number | 1080 |
| height | number | 1920 |
| timelineDuration | number | 24 |
| layers | LayerDefinition[] | 3 default layers |
validateVideoDocument(document, options?)
Validate a video document and return an array of ValidationError objects. Returns [] if valid.
Options: { knownTemplateIds?: Set<string> } — pass a set of known template IDs to validate componentType references.
normalizeVideoDocument(input?, options?)
Normalize a partial or malformed document into a valid VideoDocument.
exportVideoDocumentFromState(state?)
Export a video document from internal editor state.
getDocumentDuration(document)
Returns the effective duration — the greater of timelineDuration and the end time of the last timeline component.
getDocumentTimelineEnd(document)
Returns the end time of the last timeline component.
getTimelineWindow(components?, range?)
Filter and sort timeline components that overlap a time range { startTime?, endTime? }.
sortTimeline(components?)
Sort timeline components by startTime, then by id.
createDefaultLayers(count?)
Create an array of default layer definitions (default: 3).
Constants
| Constant | Value |
|---|---|
| DEFAULT_PROJECT_DIMENSIONS | { width: 1080, height: 1920 } |
| DEFAULT_TIMELINE_DURATION | 24 |
| PLAYER_SCHEMA_VERSION | 1 |
Player Element
defineAVSPlayerElement()
Register the <avs-player> custom element. Safe to call multiple times.
AVSPlayerElement
Extends HTMLElement. Observed attributes: src, autoplay, loop, no-controls.
Properties:
ready: Promise— resolves when the player iframe is ready
Playback:
load(document)— load a video documentloadFromUrl(url)— load a document from a URLpreloadAssets()— preload all assetsplay()/pause()/stop()/seek(time)/destroy()
Document:
createEmptyProject(options?)— create a new empty projectgetDocument()/exportDocument()/replaceDocument(document)/validateDocument(document)
Status:
getStatus()/getErrors()
Assets:
getAssets()/getAsset(assetId)/addAsset(asset)/updateAsset(assetId, patch)/removeAsset(assetId)
Timeline:
getTimeline(range?)/getComponent(componentId)/addComponent(definition)/removeComponent(componentId)/clearTimeline()updateComponent(componentId, patch)/updateComponentParams(componentId, patch)/updateComponentTiming(componentId, patch)/updateComponentAssets(componentId, patch)/updateComponentMetadata(componentId, patch)moveComponent(componentId, patch)/moveComponents(moves)
Layers:
getLayers()/addLayer(patch?)/updateLayer(layerId, patch)/removeLayer(layerId)/reorderLayers(layerIds)
Templates:
listTemplates()/getTemplate(templateId)/getComponentPanel(componentId)
Events:
on(eventName, handler)— returns unsubscribe functionoff(eventName, handler)
Test Harness
createPlayerHarness(page, options)
Create a Playwright test harness.
| Option | Type | Default |
|---|---|---|
| document | VideoDocument | required |
| playerUrl | string | "https://create.appvideostudio.com" |
| validate | boolean | true |
| width | number | 1280 |
| height | number | 720 |
| readyTimeout | number | 15000 |
Returns a PlayerHarness with methods: play, pause, seek, stop, getDocument, exportDocument, getStatus, getErrors, getAssets, getTimeline, getComponent, addComponent, updateComponentParams, updateComponentTiming, updateComponentAssets, removeComponent, replaceDocument, listTemplates, getTemplate, screenshot, screenshotAt, screenshotSequence, destroy.
Component Catalog
Browse the full interactive catalog at appvideostudio.com/api/components.
Machine-readable metadata: appvideostudio.com/api/catalog.json
Examples
Minimal embed
<script type="module">
import { defineAVSPlayerElement } from '@appvideostudio/sdk/player';
defineAVSPlayerElement();
</script>
<avs-player src="https://create.appvideostudio.com/player/"></avs-player>Build a document programmatically
import {
createEmptyVideoDocument,
validateVideoDocument,
} from '@appvideostudio/sdk';
const doc = createEmptyVideoDocument({
name: 'Programmatic Video',
timelineDuration: 15,
});
doc.assets.push({
id: 'bg-asset',
type: 'image',
name: 'Background',
url: 'https://example.com/bg.jpg',
posterUrl: null,
duration: null,
width: 1080,
height: 1920,
mimeType: 'image/jpeg',
});
doc.timeline.push({
id: 'bg-comp',
componentType: 'image-fill',
layerId: 'layer-1',
startTime: 0,
duration: 15,
params: {},
assetBindings: { source: 'bg-asset' },
customLabel: 'Background',
color: '#2563eb',
});
const errors = validateVideoDocument(doc);
if (errors.length === 0) {
console.log('Document is valid:', JSON.stringify(doc, null, 2));
}Playwright screenshot test
import { test, expect } from '@playwright/test';
import { createPlayerHarness } from '@appvideostudio/sdk/test-harness';
import { createEmptyVideoDocument } from '@appvideostudio/sdk';
test('visual regression at key frames', async ({ page }) => {
const doc = createEmptyVideoDocument({ name: 'Regression Test' });
// ... add components to doc ...
const harness = await createPlayerHarness(page, { document: doc });
const frames = await harness.screenshotSequence([0, 2, 5, 10]);
for (const { time, buffer } of frames) {
expect(buffer).toMatchSnapshot(`frame-${time}s.png`);
}
await harness.destroy();
});Load from URL
import { defineAVSPlayerElement } from '@appvideostudio/sdk/player';
defineAVSPlayerElement();
const player = document.createElement('avs-player');
document.body.appendChild(player);
await player.ready;
await player.loadFromUrl('https://example.com/my-video.json');
await player.play();Links
License
MIT
