forked from forks/ffprobe-wasm
Refactor to load wasm module in a web worker to prevent blocking main browser thread. Update FS to use WORKERFS.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
FROM emscripten/emsdk as build
|
||||
FROM emscripten/emsdk:2.0.11 as build
|
||||
|
||||
ARG FFMPEG_VERSION=4.3.1
|
||||
ARG X264_VERSION=20170226-2245-stable
|
||||
@@ -30,7 +30,7 @@ RUN cd /tmp/ && \
|
||||
wget http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \
|
||||
tar zxf ffmpeg-${FFMPEG_VERSION}.tar.gz && rm ffmpeg-${FFMPEG_VERSION}.tar.gz
|
||||
|
||||
ARG CFLAGS="-s USE_PTHREADS -O3 -I${PREFIX}/include"
|
||||
ARG CFLAGS="-s USE_PTHREADS=1 -O3 -I${PREFIX}/include"
|
||||
ARG LDFLAGS="$CFLAGS -L${PREFIX}/lib -s INITIAL_MEMORY=33554432"
|
||||
|
||||
# Compile ffmpeg.
|
||||
|
||||
3
Makefile
3
Makefile
@@ -6,7 +6,8 @@ dist/ffprobe-wasm.js:
|
||||
-I/opt/ffmpeg/include/ \
|
||||
-s EXTRA_EXPORTED_RUNTIME_METHODS="[FS, cwrap, ccall, getValue, setValue, writeAsciiToMemory]" \
|
||||
-s INITIAL_MEMORY=268435456 \
|
||||
-lavcodec -lavformat -lavfilter -lavdevice -lswresample -lswscale -lavutil -lm -lx264 \
|
||||
-pthread \
|
||||
-lavcodec -lavformat -lavfilter -lavdevice -lswresample -lswscale -lavutil -lm -lx264 -pthread \
|
||||
-lworkerfs.js \
|
||||
-o dist/ffprobe-wasm.js \
|
||||
src/ffprobe-wasm-wrapper.cpp
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <inttypes.h>
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/bind.h>
|
||||
@@ -65,8 +66,8 @@ typedef struct FramesResponse {
|
||||
int nb_frames;
|
||||
} FramesResponse;
|
||||
|
||||
FileInfoResponse get_file_info() {
|
||||
FILE *file = fopen("file", "rb");
|
||||
FileInfoResponse get_file_info(std::string filename) {
|
||||
FILE *file = fopen(filename.c_str(), "rb");
|
||||
if (!file) {
|
||||
printf("cannot open file\n");
|
||||
}
|
||||
@@ -79,9 +80,8 @@ FileInfoResponse get_file_info() {
|
||||
|
||||
// Open the file and read header.
|
||||
int ret;
|
||||
if ((ret = avformat_open_input(&pFormatContext, "file", NULL, NULL)) < 0) {
|
||||
printf("ERROR: could not open the file. Error: %d\n", ret);
|
||||
printf("%s", av_err2str(ret));
|
||||
if ((ret = avformat_open_input(&pFormatContext, filename.c_str(), NULL, NULL)) < 0) {
|
||||
printf("ERROR: %s\n", av_err2str(ret));
|
||||
}
|
||||
|
||||
// Get stream info from format.
|
||||
@@ -135,10 +135,10 @@ FileInfoResponse get_file_info() {
|
||||
return r;
|
||||
}
|
||||
|
||||
FramesResponse get_frames(int offset) {
|
||||
FramesResponse get_frames(std::string filename, int offset) {
|
||||
av_log_set_level(AV_LOG_QUIET); // No logging output for libav.
|
||||
|
||||
FILE *file = fopen("file", "rb");
|
||||
FILE *file = fopen(filename.c_str(), "rb");
|
||||
if (!file) {
|
||||
printf("cannot open file\n");
|
||||
}
|
||||
@@ -151,9 +151,8 @@ FramesResponse get_frames(int offset) {
|
||||
|
||||
// Open the file and read header.
|
||||
int ret;
|
||||
if ((ret = avformat_open_input(&pFormatContext, "file", NULL, NULL)) < 0) {
|
||||
printf("ERROR: could not open the file. Error: %d\n", ret);
|
||||
printf("%s", av_err2str(ret));
|
||||
if ((ret = avformat_open_input(&pFormatContext, filename.c_str(), NULL, NULL)) < 0) {
|
||||
printf("ERROR: %s\n", av_err2str(ret));
|
||||
}
|
||||
|
||||
// Get stream info from format.
|
||||
@@ -239,7 +238,6 @@ FramesResponse get_frames(int offset) {
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_BINDINGS(constants) {
|
||||
function("avformat_version", &c_avformat_version);
|
||||
function("avcodec_version", &c_avcodec_version);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<script src="ffprobe-wasm.js"></script>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
:value="progress"
|
||||
max="100"></b-progress>
|
||||
|
||||
<div v-if="data">
|
||||
<div v-if="info">
|
||||
<div class="mt-3">Selected file: {{ file ? `${file.name}: ${file.size} bytes` : '' }}</div>
|
||||
|
||||
<b-tabs class="mt-4">
|
||||
<b-tab title="Overview" class="mt-2">
|
||||
<div v-if="data">
|
||||
<div v-if="info">
|
||||
<Overview :info="info" />
|
||||
</div>
|
||||
</b-tab>
|
||||
@@ -39,6 +39,8 @@
|
||||
import Overview from './Overview.vue';
|
||||
import Frames from './Frames.vue';
|
||||
|
||||
const worker = new Worker('ffprobe-worker.js');
|
||||
|
||||
export default {
|
||||
name: 'File',
|
||||
components: {
|
||||
@@ -49,13 +51,14 @@ export default {
|
||||
return {
|
||||
file: null,
|
||||
data: null,
|
||||
info: null,
|
||||
progress: 0,
|
||||
showProgress: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
info() {
|
||||
return this.data && window.Module.get_file_info();
|
||||
created() {
|
||||
worker.onmessage = (e) => {
|
||||
this.info = e.data;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -65,21 +68,7 @@ export default {
|
||||
this.showProgress = true;
|
||||
|
||||
const file = event.dataTransfer ? event.dataTransfer.files[0] : event.target.files[0];
|
||||
const reader = new FileReader();
|
||||
|
||||
// reader.onload = e => this.$emit("load", event.target.result);
|
||||
reader.onload = (event) => {
|
||||
this.progress = 100;
|
||||
this.data = new Uint8Array(event.target.result);
|
||||
window.Module.FS.writeFile('file', new Uint8Array(this.data));
|
||||
setTimeout(() => { this.showProgress = false; }, 2000);
|
||||
}
|
||||
reader.onprogress = (event) => {
|
||||
if (event.lengthComputable) {
|
||||
this.progress = parseInt(((event.loaded / event.total) * 100), 10);
|
||||
}
|
||||
}
|
||||
reader.readAsArrayBuffer(file);
|
||||
worker.postMessage([ file ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<b-table stacked :items="items"></b-table>
|
||||
|
||||
<h4>Streams</h4>
|
||||
<b-table striped hover :items="streams"></b-table>
|
||||
<b-table striped hover :items="info.streams"></b-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -15,15 +15,6 @@
|
||||
export default {
|
||||
name: 'Overview',
|
||||
props: ['info'],
|
||||
computed: {
|
||||
streams() {
|
||||
const s = [];
|
||||
for (let i = 0; i < this.info.streams.size(); i++) {
|
||||
s.push(this.info.streams.get(i));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
items: [
|
||||
@@ -38,9 +29,9 @@ export default {
|
||||
],
|
||||
versions: [
|
||||
{
|
||||
libavutil: window.Module.avutil_version(),
|
||||
libavcodec: window.Module.avcodec_version(),
|
||||
libavformat: window.Module.avformat_version(),
|
||||
libavutil: this.info.versions.libavutil,
|
||||
libavcodec: this.info.versions.libavcodec,
|
||||
libavformat: this.info.versions.libavformat,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user