Server Developer
The @moviemasher/server-express package builds upon the core @moviemasher/moviemasher.js package to provide an ExpressJS server API capable of video encoding and streaming, as well as managing media and its metadata.
The server package is optimized to work with the @moviemasher/client-react package, but this is not a requirement. It defines several Server classes, each handling a specific set of functionality:
- ApiServer: handles routing of requests to other servers
- DataServer: handles storage of JSON formatted data
- FileServer: handles storage of binary media files
- RenderingServer: handles creation of video files
- StreamingServer: handles a streaming session
- WebServer: delivers static files
The interface between client and server is highly structured, with both requests and responses consisting of strongly typed JSON objects that effectively constitute the API between them. Communication is funneled through the ApiClient component on the client and the ApiServer class on the server.
Demos
Since the Demo only includes the client-side components of the system, the first step is typically to launch a fully functional one either in the cloud or locally to test out the server-side functionality.
Non-developers or anyone with an Amazon account may find launching Movie Masher within their AWS Marketplace to be the simplest option. The image available there can be used to launch an EC2 instance of any size, to which you have full access. You can even make your own images based on it, including any custom changes or additions.
Developers familar with Docker may want to launch the image available on DockerHub, either locally or within a cloud-based container service. This option provides the same ability to access the instance and build atop the image.
CJS Server Example
The source code is available in CommonJS format for direct use in NodeJS, or as TypScript for rebundling with tools like rollup.js.
Installation
The following shell command installs the server and core libraries to your NPM project,
saving the former to the dependencies
array in your package.json file.
npm install @moviemasher/server-express --save
Alternatively, if you're wanting to build your own server you can just install and build off the core library instead.
Please note
This does not install a client implementation that interacts with this package. Learn more about how the codebase is structured in the Architecture Overview.
Inclusion
In this example we're using the Host class to construct all the Server instances, using arguments provided by the HostDefaultOptions function. We pass this function a parsed JSON file with the following structure:
In the configuration we are setting the preview dimensions to their default for demonstration purposes. The server will pass these to the client and the client will apply them, but only after the CSS is applied so a resize will be visible if they differ. Preview dimensions should be overridden either in the client, or better still, in the CSS. If the defaults are overidden there they should be here too, since the client does NOT pass them to the server. The rendering server uses them to optimally size previews of uploaded video and images.
We are also setting the output dimensions here, which are used as default values for both the rendering and streaming servers. They should always be an even multiple of the preview dimensions - in this case it's a multiple of four. Using different aspect ratios is actually supported, but then the preview in the client will not match the output of these servers.
API Server
The ApiServer provides a high-level routing mechanism to other servers, through two endpoints:
Endpoint | Request Interface | Response Interface |
---|---|---|
/api/servers | ApiServersRequest | ApiServersResponse |
/api/callbacks | ApiCallbacksRequest | ApiCallbacksResponse |
The /api/servers
endpoint is called initially to determine which other servers are enabled, and retrieve any client configuration for them. Before making subsequent requests to another server, the /api/callbacks
endpoint is first requested. This endpoint returns the actual request that the client should make, potentially from another server. By default though, the same server is returned.
Data Server
The DataServer is responsible for storing and retrieving JSON formatted data and metadata related to binary files. Specifically, it stores the following types of objects:
- MashObject
- CastObject
- VideoDefinitionObject
- AudioDefinitionObject
- ImageDefinitionObject
- FontDefinitionObject
- VideoSequenceDefinitionObject
Its endpoints support typical CRUD (create, retrieve, update, delete) operations:
Endpoint | Request Interface | Response Interface |
---|---|---|
/data/cast/delete | DataCastDeleteRequest | DataCastDeleteResponse |
/data/cast/get | DataCastGetRequest | DataCastGetResponse |
/data/cast/put | DataCastPutRequest | DataCastPutResponse |
/data/cast/retrieve | DataCastRetrieveRequest | DataCastRetrieveResponse |
/data/cast/default | DataCastDefaultRequest | DataCastDefaultResponse |
/data/mash/delete | DataMashDeleteRequest | DataMashDeleteResponse |
/data/mash/get | DataMashGetRequest | DataMashGetResponse |
/data/mash/put | DataMashPutRequest | DataMashPutResponse |
/data/mash/retrieve | DataMashRetrieveRequest | DataMashRetrieveResponse |
/data/mash/default | DataMashDefaultRequest | DataMashDefaultResponse |
/data/definition/delete | DataDefinitionDeleteRequest | DataDefinitionDeleteResponse |
/data/definition/get | DataDefinitionGetRequest | DataDefinitionGetResponse |
/data/definition/put | DataDefinitionPutRequest | DataDefinitionPutResponse |
/data/definition/retrieve | DataDefinitionRetrieveRequest | DataDefinitionRetrieveResponse |
The client will typically request /data/mash/default
or /data/cast/default
in order to initially populate the Player and Timeline components. If the user has yet to create a Mash or Cast then an empty one is returned, otherwise the most recently created one is returned. A request is also made to /data/mash/retrieve
or /data/cast/retrieve
to populate the SelectEditedControl component.
The client will likely also start requesting /data/definition/retrieve
in order to populate the Browser component. This accepts a types
key in its argument to limit each request to a subset of DefinitionTypes, as dictated by the currently selected BrowserPicker component.
The /data/*/put
endpoints essentially act as UPSERT (update or insert) mechanisms, depending on the optional id
key provided in the object being saved. If it's undefined or prefixed by the data.temporaryIdPrefix
value that was provided in the client configuration, then a new unique identifier is generated and the object is inserted into storage, otherwise an existing object is updated.
File Server
The FileServer currently only supports a single endpoint that handles uploading of binary files:
Endpoint | Request Interface | Response Interface |
---|---|---|
/file/store | FileStoreRequest | FileStoreResponse |
It is not typically called directly, but rather triggered as a callback from /rendering/upload
(see below).
Rendering Server
The RenderingServer produces media files, with the help of Fluent FFmpeg. The processing is asynchronous, so the API supports both starting a rendering job and retrieving its current status:
Endpoint | Request Interface | Response Interface |
---|---|---|
/rendering/start | RenderingStartRequest | RenderingStartResponse |
/rendering/status | RenderingStatusRequest | RenderingStatusResponse |
/rendering/upload | RenderingUploadRequest | RenderingUploadResponse |
The /rendering/start
endpoint initiates a rendering process and returns a callback to /rendering/status
. This endpoint keeps returning a callback to itself until the rendering process is complete. If a Mash was being rendering, a URL to the rendered file is returned in the final response.
Users are able to import new media into the Browser without server interaction.
The /rendering/upload
endpoint is called for each new import as part of the saving process.
This accepts metadata related to the file in its argument and returns two callbacks - one to /file/store
to handle the file upload request itself, and another to /rendering/start
that's executed afterwards. The later request may, depending on file type, specify several renderings producing multiple files. For instance, uploading a video file produces:
- an icon file for display in the Browser component
- an MP3 file containing the video's soundtrack
- a sequence of images representing the video's frames
The client uses these files exclusively, while the server will use the original upload whenever it subsequently renders or streams the video. Once all the files are generated for an upload the /rendering/status
endpoint returns one final callback to /data/definition/put
which saves and returns a DefinitionObject representing it.
Streaming Server
The StreamingServer produces a video stream from a Cast, potentially pushing it to another server.
Endpoint | Request Interface | Response Interface |
---|---|---|
/streaming/start | StreamingStartRequest | StreamingStartResponse |
/streaming/status | StreamingStatusRequest | StreamingStatusResponse |
/streaming/delete | StreamingDeleteRequest | StreamingDeleteResponse |
/streaming/preload | StreamingPreloadRequest | StreamingPreloadResponse |
/streaming/cut | StreamingCutRequest | StreamingCutResponse |
/streaming/webrtc | StreamingWebrtcRequest | StreamingWebrtcResponse |
/streaming/rtmp | StreamingRtmpRequest | StreamingRtmpResponse |
/streaming/remote | StreamingRemoteRequest | StreamingRemoteResponse |
/streaming/local | StreamingLocalRequest | StreamingLocalResponse |
Warning | |
---|---|
This API is experimental and likely to change in subsequent versions, without being considered a 'breaking change' with regards to version number. |