Skip to content

Commit

Permalink
Merge a0d109d into b2a8b35
Browse files Browse the repository at this point in the history
  • Loading branch information
thijstriemstra committed Jan 30, 2021
2 parents b2a8b35 + a0d109d commit 49c0c3b
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- New opus-media-recorder plugin: provides cross-browser Opus codec support with
various audio formats such as Ogg and WebM (#355)
- Bump required version for videojs-wavesurfer (3.4.0 or newer)


## 4.1.1 - 2020/11/01
Expand Down
10 changes: 10 additions & 0 deletions build-config/fragments/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ module.exports = {
console.log(colors.green(' [examples] wasm mime-type handler ready'));
console.log('');

// ========================================================
// use proper headers for SharedArrayBuffer on Firefox
// see https://github.com/ffmpegwasm/ffmpeg.wasm/issues/102
// ========================================================
app.use((req, res, next) => {
res.header('Cross-Origin-Opener-Policy', 'same-origin');
res.header('Cross-Origin-Embedder-Policy', 'require-corp');
next();
});

// =============================================
// file upload handler for simple upload example
// =============================================
Expand Down
104 changes: 104 additions & 0 deletions examples/plugins/video-only-ffmpegwasm.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ffmpeg.wasm video-only example - Record Plugin for Video.js</title>

<link href="../../node_modules/video.js/dist/video-js.min.css" rel="stylesheet">
<link href="../../dist/css/videojs.record.css" rel="stylesheet">
<link href="../assets/css/examples.css" rel="stylesheet">

<script src="../../node_modules/video.js/dist/video.min.js"></script>
<script src="../../node_modules/recordrtc/RecordRTC.js"></script>
<script src="../../node_modules/webrtc-adapter/out/adapter.js"></script>
<script src="../../node_modules/@ffmpeg/ffmpeg/dist/ffmpeg.min.js"></script>

<script src="../../dist/videojs.record.js"></script>
<script src="../../dist/plugins/videojs.record.ffmpeg-wasm.js"></script>

<script src="../browser-workarounds.js"></script>

<style>
/* change player background color */
#myVideo {
background-color: #F5BDAB;
}
</style>
</head>
<body>

<video id="myVideo" playsinline class="video-js vjs-default-skin"></video>

<script>
/* eslint-disable */
var options = {
controls: true,
width: 320,
height: 240,
fluid: false,
bigPlayButton: false,
controlBar: {
volumePanel: false
},
plugins: {
record: {
audio: false,
video: true,
maxLength: 20,
debug: true,
displayMilliseconds: false,
convertEngine: 'ffmpeg.wasm',
// convert recorded data to MP3
convertOptions: ['-f', 'mp3', '-codec:a', 'libmp3lame', '-qscale:a', '2'],
// specify MP3 output mime-type
pluginLibraryOptions: {
outputType: 'audio/mpeg'
},
convertWorkerURL: '../../node_modules/@ffmpeg/core/dist/ffmpeg-core.js'
}
}
};

// apply some workarounds for opera browser
applyVideoWorkaround();

var player = videojs('myVideo', options, function() {
// print version information at startup
videojs.log('Using video.js', videojs.VERSION,
'with videojs-record', videojs.getPluginVersion('record'),
'and recordrtc', RecordRTC.version);
});
// error handling
player.on('deviceError', function() {
console.log('device error:', player.deviceErrorCode);
});
player.on('error', function(element, error) {
console.error(error);
});

// user clicked the record button and started recording
player.on('startRecord', function() {
console.log('started recording!');
});

// converter started processing
player.on('startConvert', function() {
console.log('started converting!');
});

// user completed recording and stream is available
player.on('finishRecord', function() {
// the blob object contains the recorded data that
// can be downloaded by the user, stored on server etc.
console.log('finished recording: ', player.recordedData);
});

// converter completed and stream is available
player.on('finishConvert', function() {
// the convertedData object contains the recorded data that
// can be downloaded by the user, stored on server etc.
console.log('finished converting: ', player.convertedData);
});
</script>
</body>
</html>
52 changes: 45 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,16 @@
"dependencies": {
"recordrtc": ">=5.6.1",
"video.js": ">=7.0.5",
"videojs-wavesurfer": ">=3.3.0",
"videojs-wavesurfer": ">=3.4.0",
"webrtc-adapter": ">=7.7.0"
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/plugin-transform-runtime": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/register": "^7.12.10",
"@ffmpeg/core": "^0.8.5",
"@ffmpeg/ffmpeg": "^0.9.7",
"@mattiasbuelens/web-streams-polyfill": "^0.3.2",
"add-zero": "^1.0.0",
"babel-loader": "^8.2.2",
Expand Down Expand Up @@ -121,7 +123,7 @@
"lamejs": ">=1.2.0",
"libvorbis.js": ">=1.1.2",
"log-timestamp": "^0.3.0",
"mini-css-extract-plugin": "^1.3.4",
"mini-css-extract-plugin": "^1.3.5",
"node-fs-extra": "^0.8.2",
"node-static": "^0.7.11",
"npm-run-all": "^4.1.5",
Expand Down
4 changes: 2 additions & 2 deletions src/js/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ const pluginDefaultOptions = {
imageOutputQuality: 0.92,
// Accepts numbers in milliseconds; use this to force intervals-based blobs.
timeSlice: 0,
// Media converter library to use. Legal values are 'ts-ebml' and 'ffmpeg.js'.
// Use an empty string '' to disable (default).
// Media converter library to use. Legal values are 'ts-ebml', 'ffmpeg.wasm'
// and 'ffmpeg.js'. Use an empty string '' to disable (default).
convertEngine: '',
// URL for the converter worker.
convertWorkerURL: '',
Expand Down
5 changes: 3 additions & 2 deletions src/js/engine/convert-engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ const Component = videojs.getComponent('Component');
// supported convert plugin engines
const TSEBML = 'ts-ebml';
const FFMPEGJS = 'ffmpeg.js';
const FFMPEGWASM = 'ffmpeg.wasm';

// all convert plugins
const CONVERT_PLUGINS = [TSEBML, FFMPEGJS];
const CONVERT_PLUGINS = [TSEBML, FFMPEGJS, FFMPEGWASM];

/**
* Base class for converter backends.
Expand Down Expand Up @@ -76,5 +77,5 @@ videojs.ConvertEngine = ConvertEngine;
Component.registerComponent('ConvertEngine', ConvertEngine);

export {
ConvertEngine, CONVERT_PLUGINS, TSEBML, FFMPEGJS
ConvertEngine, CONVERT_PLUGINS, TSEBML, FFMPEGJS, FFMPEGWASM
};
7 changes: 6 additions & 1 deletion src/js/engine/engine-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import videojs from 'video.js';

import RecordRTCEngine from './record-rtc';
import {CONVERT_PLUGINS, TSEBML, FFMPEGJS} from './convert-engine';
import {CONVERT_PLUGINS, TSEBML, FFMPEGJS, FFMPEGWASM} from './convert-engine';
import {RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS, OPUSRECORDER, OPUSMEDIARECORDER, VMSG, WEBMWASM, AUDIO_PLUGINS} from './record-engine';

/**
Expand Down Expand Up @@ -124,6 +124,11 @@ const getConvertEngine = function(convertEngine) {
ConvertEngineClass = videojs.FFmpegjsEngine;
break;

case FFMPEGWASM:
// ffmpeg.wasm
ConvertEngineClass = videojs.FFmpegWasmEngine;
break;

default:
// unknown engine
throw new Error('Unknown convertEngine: ' + convertEngine);
Expand Down
98 changes: 98 additions & 0 deletions src/js/plugins/ffmpeg-wasm-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* @file ffmpeg-wasm-plugin.js
* @since 4.2.0
*/

import videojs from 'video.js';

const ConvertEngine = videojs.getComponent('ConvertEngine');

/**
* Converter engine using the ffmpeg.wasm library.
*
* @class
* @augments videojs.ConvertEngine
*/
class FFmpegWasmEngine extends ConvertEngine {
/**
* Creates an instance of this class.
*
* @param {Player} player
* The `Player` that this class should be attached to.
*
* @param {Object} [options]
* The key/value store of player options.
*/
constructor(player, options) {
super(player, options);

/**
* Enables console logging for debugging purposes.
*
* @type {boolean}
*/
this.debug = false;
/**
* Path to script `ffmpeg-core.js`.
*
* @type {string}
*/
this.convertWorkerURL = './node_modules/@ffmpeg/core/dist/ffmpeg-core.js';
/**
* Mime-type for output.
*
* @type {string}
*/
this.outputType = null;
/**
* Additional configuration options for the ffmpeg.wasm library.
*
* @type {object}
*/
this.pluginLibraryOptions = {};
}

/**
* Inject metadata.
*
* @param {Blob} data - Recorded data that needs to be converted.
*/
async convert(data) {
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({
corePath: this.convertWorkerURL,
log: this.debug
});
const name = "foo";

// save timestamp
const timestamp = new Date();
timestamp.setTime(data.lastModified);

// notify listeners
this.player().trigger('startConvert');

// load and convert blob
await ffmpeg.load();
ffmpeg.FS('writeFile', name, await fetchFile(data));
await ffmpeg.run('-i', name, 'output.mp4');
const output = ffmpeg.FS('readFile', 'output.mp4');

// create new blob
let result = new Blob([output.buffer], {type: 'video/mp4'});

// add existing file info
this.addFileInfo(result, timestamp);

// store result
this.player().convertedData = result;

// notify listeners
this.player().trigger('finishConvert');
}
}

// expose plugin
videojs.FFmpegWasmEngine = FFmpegWasmEngine;

export default FFmpegWasmEngine;
2 changes: 1 addition & 1 deletion src/js/plugins/ffmpegjs-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class FFmpegjsEngine extends ConvertEngine {
*/
this.outputType = null;
/**
* Additional configuration options for the opus-recorder library.
* Additional configuration options for the ffmpeg.js library.
*
* @type {object}
*/
Expand Down

0 comments on commit 49c0c3b

Please sign in to comment.