Video Editor exported methods
The video editor extension isn't included in the Pintura image editor product package, it's available as an upgrade on the pricing page
Please note that client-side video encoding is useful for encoding short videos, it's advised to use server side encoding for content longer than a couple minutes.
The Redact, Frame, and Fill util are currently not supported when using the video extension.
The functions, properties, and defaults related to video editing that are exported by the Pintura Video module.
These exports are available on the pinturavideo
module.
Export | Description |
---|---|
createDefaultVideoWriter(options) |
Creates a default video writer. This is the array of processes the editor uses to write video data. |
createMediaStreamEncoder(options) |
Creates a video encoder that uses the native MediaStream API to generate a video file. |
createMuxerEncoder(options) |
Creates a video encoder that uses the native VideoEncoder API to generate a video file. |
createFFmpegEncoder(options) |
Creates a video encoder that uses FFmpeg WASM to generate a video file. |
createDefaultVideoWriter
The createDefaultVideoWriter
function returns a default video writer array. This is an array of processes the editor runs to write the output video data.
The createDefaultImageWriter
function shares the following properties with the createDefaultVideoWriter
function:
import { imageStateToCanvas } from '@pqina/pintura';
import {
createDefaultVideoWriter,
createMediaStreamEncoder,
} from '@pqina/pintura-video';
openDefaultEditor({
imageWriter: createDefaultVideoWriter({
// Resize image
targetSize: {
width: 512,
},
// Use media stream encoder
encoder: createMediaStreamEncoder({
// Required
imageStateToCanvas,
}),
}),
});
createMediaStreamEncoder
This video encoder is based on the native browser MediaStream API.
The MediaStream encoder works well for shorter video's but most likely isn't an option for longer videos. For longer video's using the FFmpegEncoder or using server side FFmpeg is probably a better idea.
At this time this technology has some limitations:
- The duration of the save process is equal to the trimmed video time.
- The browser tab needs to stay active for video creation process to work.
- If the user device is very slow the created video can have missing frames.
- Safari can only start processing the video after the user has interacted with the page or has been on the page for about 7 seconds.
- Chrome creates a WebM or MP4 video with no duration information, this can sometimes be corrected by passing the output video file through this third party library but it unfortunately doesn't work consistently.
Please refrain from using only the MediaStream encoder. Even with the WebM duration fix Chrome has trouble exporting valid video files.
It's better to create a chain of encoders like shown in the createMuxerEncoder example, and use the MediaStream encoder as a fallback.
import { openDefaultEditor, imageStateToCanvas } from './pintura.js';
import {
createDefaultVideoWriter,
createMediaStreamEncoder,
} from './pinturavideo.js';
openDefaultEditor({
imageWriter: createDefaultVideoWriter({
// Resize image
targetSize: {
width: 512,
},
// Use media stream encoder
encoder: createMediaStreamEncoder({
// Required
imageStateToCanvas,
// output quality (optional)
videoBitrate: 2500000, // 2.5MBps
audioBitrate: 192000, // 192KBps
// Default FPS (optional)
framesPerSecond: 24,
// By default logging is disabled
log: false,
// Force a mime type, please note that this won't work on each browser.
// By default this property is undefined and Pintura will search a mime type.
mimeType: 'video/webm;codecs=vp9,opus',
// If the `mimeType` property isn't set the `mimeTypes` property allows us to define a list of mime types to test in order.
// These are the default values.
mimeTypes: [
// MP4 if at all possible
'video/mp4;codecs=avc1,aac',
'video/mp4;codecs=avc,aac',
'video/mp4;codecs=mp4a,aac',
'video/mp4;codecs=h264,aac',
'video/mp4',
// WEBM will usually work
'video/webm;codecs=vp9,opus',
'video/webm;codecs=vp8,opus',
'video/webm;codecs=h264,opus',
'video/webm',
// Matroska fallback for Linux
'video/x-matroska;codecs=avc1,opus',
'video/x-matroska;codecs=vp9,opus',
'video/x-matroska;codecs=vp8,opus',
'video/x-matroska',
],
}),
}),
});
createMuxerEncoder
This video encoder is based on the native browser VideoEncoder API.
This encoder uses the MIT licensed webm-muxer or the mp4-muxer as a dependency.
This encoder doesn't have the disadvantages listed for the MediaStream encoder but currently only works on the latest versions of Chrome.
See the Video Encoder and Audio Encoder API Browser Compatibility tables for an up to date list of browsers that support the API.
import * as Mp4Muxer from 'mp4-muxer';
import {
openDefaultEditor,
imageStateToCanvas,
createDefaultImageWriter,
createDefaultMediaWriter,
} from './pintura.js';
import {
createMuxerEncoder,
createDefaultVideoWriter,
createMediaStreamEncoder,
} from './pinturavideo.js';
openDefaultEditor({
// here we supply two video writers
imageWriter: createDefaultMediaWriter(
{
// Generic options writer options
},
[
// For writing images
createDefaultImageWriter(),
// Use muxer to encode videos
createDefaultVideoWriter({
encoder: createMuxerEncoder({
// when using the mp4 muxer we need to set video/mp4 mimetype
muxer: Mp4Muxer,
mimeType: 'video/mp4',
// video and audio bitrate to use (optional)
videoBitrate: 2500000, // 2.5MBps
audioBitrate: 192000, // 192KBps, should be either (96000, 128000, 160000, or 192000)
// this draws the image
imageStateToCanvas,
// enable logging
log: true,
}),
}),
// Media stream as fallback
createDefaultVideoWriter({
encoder: createMediaStreamEncoder({
imageStateToCanvas,
}),
}),
]
),
});
createFFmpegEncoder
To use the FFmpeg encoder we need to download and install FFmpeg WASM.
Please make sure to read the FFmpeg GitHub page before proceeding.
Based on the example below the FFmpeg WASM package dist
folder contents should be saved to ./ffmpeg/
The FFmpeg WASM Core package dist
folder contents should be saved to ./ffmpeg/core/
Resulting in the following directory structure:
example
├─ index.html
├─ pintura
├─ pintura-video
└─ ffmpeg
├─ core
│ ├─ ffmpeg-core.js
│ ├─ ffmpeg-core.wasm
│ └─ ffmpeg-core.worker.js
├─ ffmpeg.min.js
└─ ffmpeg.min.js.map
import { openDefaultEditor, imageStateToCanvas } from './pintura/pintura.js';
import {
createDefaultVideoWriter,
createFFmpegEncoder,
} from './pintura-video/pinturavideo.js';
openDefaultEditor({
imageWriter: createDefaultVideoWriter({
// Resize image
targetSize: {
width: 512,
},
// Use FFmpeg encoder
encoder: createFFmpegEncoder({
// References to FFmpeg
scriptPath: './ffmpeg/ffmpeg.min.js',
corePath: './ffmpeg/core/ffmpeg-core.js',
// Used to render annotations
imageStateToCanvas,
// Default output quality (optional)
videoBitrate: '384k',
audioBitrate: '48k',
// Default FPS (optional)
framesPerSecond: 24,
// Toggle logging (optional)
log: true,
}),
}),
});
FFmpeg WASM makes use of SharedArrayBuffer which is only available on webpages that are cross-origin isolated. Your server needs to return these two headers Cross-Origin-Embedder-Policy: require-corp
and Cross-Origin-Opener-Policy: same-origin
for SharedArrayBuffer to be available.
To enabled SharedArrayBuffer for local testing with Chrome:
Windows:
chrome --enable-features=SharedArrayBuffer
MacOS:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --enable-features=SharedArrayBuffer
The FFmpeg package clocks in at 25MB so it's wise to first consider the user network connection before downloading the package.
Alternatively we can generate the output video on the server, that way we bypass both
the FFmpeg WASM download size and the MediaStream API limitations. Please see the FFmpeg encoder function contained in pinturavideo.js
for the FFmpeg commands used.