JavaScript video editor, encoder, and streamer - version 5.0.6

Architecture

The Movie Masher codebase is organized as a monorepo which is made available in GitHub as moviemasher/moviemasher.js. This repository contains and builds several packages which are made available in NPM:

All code is written in TypeScript as strongly-typed ECMAScript modules utilizing named exports. External libraries are imported as peer dependencies to simplify bundling. Any modern JavaScript transpiler should be able to treeshake, split, or otherwise repackage the code to produce a bundle best optimized for final delivery.

Repository Structure

  • dev - shared configuration and assets
  • docs - a local copy of this documentation
  • node_modules - installed module depedencies
  • packages - published NPM modules
    • client-react
    • moviemasher.js
    • server-express
  • workspaces - example deployents
    • example-express-react
    • example-react
  • Dockerfile.cnf - Docker image configuration
  • package.json - shared dependecies and scripts

moviemasher.js

The core moviemasher.js NPM package has no dependencies, though portions do rely on browser APIs not natively available in all execution environments. It defines core interfaces into Movie Masher's data structures and classes, ultimately enabling playback and composition of a variety of media assets within both client and server contexts.

Core interfaces include Mash which organizes assets into an edit decision list (EDL), and MashEditor which provides methods to edit it and selectively composite its content. Learn more about how mashes are composited within different contexts in the Rendering Guide.

Similarly, the Cast interface organizes mashes for use within a streaming session, while CastEditor provides methods to edit it and selectively composite its content. Learn more about how mashes are composited by streams in the Streaming Guide.

In both cases, editors handle JSON serialization of their respective content for transport between client and server. During editing they encapsulate each operation within a discrete Action to support undo/redo history. When compositing visual content they use patterns and concepts established by FFmpeg like FilterGraph and FilterChain.

client-react

The client-react NPM package depends on moviemasher.js plus react, with examples using react-dom. It defines dozens of interoperable ReactJS function components that can be combined to fit a wide variety of uses within a custom video editing application.

The ApiClient component provides a central mechanism for other components like Webrtc that interact with a remote Server. It interacts with the ApiServer to determine which other servers are supported, and map each Endpoint to an actual ApiCallback request. It provides an ApiContext for child components to quickly see if their server is supported and retrieve a fetch promise for each request. Learn more about customizing server interaction in the Integration Guide.

The Masher and Caster components sit atop the MashEditor and CastEditor interfaces. The former can be placed inside the later, since a Cast contains at least one Mash that can be edited. Both components provide context for child components to access the underlying editor, call its methods, and display its content.

Higher level components like Player and Timeline logically organize particular functionality, in this case Mash display and Track editing. They both provide context for specific child components like PlayerButton and TimelineScrubber to operate within. For Cast display and Layer editing the Streamer and Layers components provide similiar functionality. The Browser and Inspector components provide a unified context for adding and altering content. Learn more about creating custom user interfaces in the Layout Guide.

server-express

The server-express NPM package depends on moviemasher.js plus express, sqlite, fluent-ffmpeg, node-media-server, and wtrc. It defines a collection of ExpressJS components responsible for housing content on a server and transforming it into rendered files and streams.

The ApiServer is called by the ApiClient component to map each Endpoint to an ApiCallback request before the client actually makes it. The base implementation just maps back to the same server, but subclasses can use this mechanism to dynamically route traffic to other servers. The client caches mapping based on a time-to-live (TTL) value supplied by the server, so routing can potentially be per-request. Learn more about customizing client interaction in the Integration Guide.

The DataServer and FileServer store and deliver user JSON data and media assets respectively. The base implementations use a local database and the file system, but subclasses can swap out homespun or cloud-based solutions.

The RenderingServer renders a Mash into common video, audio, or image formats while the StreamingServer streams a Cast in common formats. The default implementations both rely on Fluent FFmpeg which closely maps to FFmpeg arguments, so subclassing is possible. Learn more about server encoding in the Rendering Guide and Streaming Guide.