@krizaka/video
Vidéo derrière un seul port : téléversements reprenables signés côté serveur, jetons de lecture et liens HLS signés, statuts de webhook signés.
Installer
npm install @krizaka/videoAussi publié en sous-chemins : @krizaka/video/testkit.
Le README ci-dessous est celui du paquet sur npm, en anglais.
Video behind one port: server-signed resumable uploads, playback tokens and signed links, webhook statuses. Bunny Stream is the first adapter (streamVideo); the port is open to others. The client never holds a library key. No vendor SDK, no environment variable, no wall clock.
- Uploads.
createVideothenuploadSession(videoId, ttl): a TUS endpoint and the four headers (AuthorizationSignature,AuthorizationExpire,VideoId,LibraryId), signed on the server for this video only. - Playback.
viewToken(videoId, ttl, "embed" | "mobile")(the embedded web player's token, or the mobile SDKs'; the lifetime is passed in, 1 to 5 minutes is the norm) andplaybackUrls(videoId, ttl): the HLS playlist signed for the whole video directory (the token sits in the path, so every rendition and segment is covered) and a signed poster. - Webhooks.
parseWebhook(rawBody, headers)verifies the HMAC-SHA256 of the raw body with the library's read-only key, in constant time, and answers{ videoId, status }(ready,playable,failed,upload_failed…); a status it does not track answersnull. - Proofs. The formulas come from Bunny's documentation (TUS, embedded view token, mobile SDK token, webhooks) and the CDN forms are the ones run in production. The documentation publishes no expected outputs, so the tests compute them independently from the documented formulas and never use an invented vector.
- Not here yet. Captions, collections and listing are follow-ups.
import { streamVideo } from "@krizaka/video";
const video = streamVideo({ libraryId, libraryKey, tokenKey, readOnlyKey, cdnHostname, fetch, clock });
const { videoId } = await video.createVideo({ title: "Moment" });
const session = video.uploadSession(videoId, 3600); // hand it to the client's TUS uploader
const { token, expires } = video.viewToken(videoId, 120, "embed");videoProviderContract (@krizaka/video/testkit) is the contract every adapter runs.
Apache-2.0.
Exports
Les 19 noms que le paquet exporte, lus dans ses types.
| Nom | Nature | Ce que c’est |
|---|---|---|
Clock | type | |
embedToken | fonction | The token of the embedded web player (Stream docs, « Embedded view token authentication »): hex SHA-256 of tokenKey + videoId + expires. |
FetchLike | type | The part of fetch the adapters use: inject the global one (fetch), or a fake in a test. |
mobileViewToken | fonction | The token of the mobile SDKs (Stream docs, « Token authentication with Mobile SDKs »): HMAC-SHA256, keyed by the library API key, over `libraryKey + videoId… |
PlaybackUrls | type | |
signedDirectoryUrl | fonction | CDN token authentication for a DIRECTORY (a video's playlist, renditions and segments): SHA-256 of key + path + expires + [ip] + "token_path=" + path, URL-… |
signedFileUrl | fonction | CDN token authentication for ONE FILE (a poster, a preview): SHA-256 of key + path + expires, URL-safe base64, sent as ?token=…&expires=…. |
streamVideo | fonction | Bunny Stream, behind the VideoProvider port. |
StreamVideoOptions | type | |
tusSignature | fonction | The signature of a TUS upload (Stream docs, « TUS resumable uploads »): hex SHA-256 of libraryId + libraryKey + expires + videoId, concatenated with no sep… |
UploadSession | type | Where a client uploads, resumably (TUS), and the headers it must send: short-lived, for this video only. |
VIDEO_CODE | constante | |
VIDEO_STATUS | constante | |
VideoCode | type | |
VideoError | classe | |
VideoEvent | type | What a provider's webhook says happened to one video. |
VideoProvider | type | One video provider. |
VideoStatus | type | |
ViewToken | type | A token the player is given for one video. |
@krizaka/video/testkit
| Nom | Nature | Ce que c’est |
|---|---|---|
videoProviderContract | fonction | What every VideoProvider must do: the same behaviour behind the same port. |
Paquet
| Version sur npm | 0.2.2 (npm) |
| Licence | Apache-2.0 |
| Node.js | >=22 |
| Dépendances | @krizaka/db workspace:^ |
| Dépendances à fournir | vitest >=4 |
| Code source | video |
Journal des versions
0.2.2
Patch changes
- The READMEs, comments and published declarations no longer name the products that left the organisation (krizaka/.github#413, rule
no-departed-published). The sources were cleaned in #262 with an empty changeset, so the published tarballs still carried the old text; this release replaces them. No behaviour change.
0.2.1
Patch changes
- Updated dependencies [0d19b64]
- @krizaka/[email protected]
0.2.0
Minor changes
- New packages (#44).
@krizaka/storage: theObjectStoreport (put,get,head,delete,list,signedUrl,publicUrl),remoteStore(HTTP zone, token-signed links),bucketStore(any S3-compatible service, Signature V4 checked against AWS's vectors),folderStore,memoryObjectStore,createStorage(size limit passed in, declared layout, magic-number check, content-hashed names),checkEndpoint,@krizaka/storage/settings(storage.providerlocal / http / s3, limits and coordinates;storeFromSettings) andobjectStoreContract.@krizaka/video: theVideoProviderport,streamVideo(Bunny Stream: create, delete, server-signed TUS sessions, embed and mobile view tokens, signed HLS and poster links, signed webhooks), the signing helpers andvideoProviderContract.
@krizaka/coupons
Des coupons de rabais et de crédits gérés par l’admin : réservés sous verrou, confirmés une fois, libérés si non payés, remboursés ; des partenaires pour l’attribution.
@krizaka/storage
Fichiers derrière un seul port : noms hachés par le contenu, liens signés et publics ; une zone HTTP, tout bucket compatible S3 ou un dossier, au choix de l'admin ; octets vérifiés par nombre magique.