Skip to content

Store large files and play video and audio - document management, the SDK and the CLI ​

The real problem ​

Northwind keeps training videos in document management. A video can be several gigabytes. Staff watch it in the browser, a few people may download it, and everyone else may only watch. The video must start playing at once, even while the server is still preparing faster copies of it.

The idea in one minute ​

  • Document management (DMS) is its own product. It has its own dms schema in each tenant database, and other features reach it only through one door (the Dms service), never its tables.
  • Large files go up in parts. The upload is cut into parts (16 MB by default), each part can be sent again, and an interrupted upload can resume. The default limit is 10 GB.
  • Playing never waits. For a video or audio file the server cuts adaptive copies in the background: 6-second chunks at several qualities (video 240p up to 1080p, never above the source; audio 64, 128 and 192 kbps). The player starts on the original file by ranges, then moves to the adaptive stream. It asks for chunks, never the whole file.
  • Rights decide what a person can do. The view right plays; the download right also shows a Download button. A viewer who only has view gets no download button, no save-as menu and no download address.
  • Playback addresses are signed and expire after 4 hours. A video element cannot send a sign-in header, so the signed address is the credential.

Designer path (Studio) ​

  1. Open the file manager and choose Upload. A file over 25 MB goes up in parts, with a progress bar and retries.
  2. In a page, add the Video player or Audio player block and set fileId to the file. Two switches: allowDownload (default on, still needs the right) and adaptive (default on).
  3. To let portal members watch, put the file in a folder the portal library shows. Members see a Play button on video and audio files.

Code path (SDK) ​

ts
import { createAuthoringClient } from "@erp/authoring-client";
const client = createAuthoringClient({ baseUrl, tenantId, token });

const file = await client.dms.uploadLarge(bigFile, { cabinetId: 1, folderId: 7 }, {
  onProgress: (sent, total) => console.log(sent, total),
});

const play = await client.dms.playback(file.id);   // { streamUrl, adaptiveUrl, canDownload, downloadUrl, expiresAt }

uploadLarge retries a failed part three times and skips parts the server already has. Pass resumeId to continue an earlier upload.

Code path (CLI and MCP) ​

bash
erp plugin op dms-cabinets
erp plugin op dms-upload-start --json '{"cabinetId":1,"folderId":7,"name":"welcome.mp4","size":734003200}'
erp plugin op dms-upload-status --id <uploadId>      # which parts arrived
erp plugin op dms-media --id 42                       # queued | processing | ready | failed | unavailable
erp plugin op dms-media-prepare --id 42 --force true # make the adaptive copies again
erp plugin op dms-playback --id 42                    # a signed address for this person

Sending the bytes of each part is done by the SDK (uploadLarge) or by PUT /api/v1/files/uploads/{id}/parts/{n} with the raw bytes; the CLI operations above start, check and prepare, and do not carry file bytes.

Safety and limits ​

  • Server needs ffmpeg for the adaptive copies. The standard image has it. Where it is missing, the original is played by ranges and the status shows unavailable.
  • Adaptive copies are made on the web server for now, one at a time. Move this to a worker before heavy use.
  • The disk store streams. S3, MinIO, Azure and GCS stores work but hold a file in memory while moving it, so keep very large files on disk storage for now.
  • Not built: captions, a speed menu, seek thumbnails, per-viewer watermarks and DRM.
  • If no permission rule is set for DMS, every signed-in user is allowed, as for every other DMS action. Set the rules in the Permission Designer.

Seeing what happened ​

  • dms-media shows the state of the adaptive copies for a file.
  • document_audit records document actions.
  • A refused playback says why in its message (no right, file gone, playback not set up on this server).
  • Developers can read the server's log with the erp_tail_logs MCP tool.

Where next ​