Daftar bagian terjemahan seri:
- Memasak
- Kompilasi dengan Emscripten (Anda ada di sini)
- Konversi avi ke mp4
Dimulai dengan bagian ini, materi akan lebih rumit, jadi jangan ragu untuk google selama membaca, jika Anda tidak mengerti apa yang terjadi.
Selain itu, saya akan mencoba mendokumentasikan solusi untuk masalah yang mungkin terjadi sehingga Anda dapat mengkompilasi perpustakaan dengan pengaturan Anda.
Pada bagian ini kita akan menganalisis:
- Cara mengatur lingkungan untuk Emscripten di Docker
- Menggunakan emconfigure dan emmake
- Bagaimana mengatasi masalah saat kompilasi FFmpeg dengan Emscripten
Cara mengatur lingkungan untuk Emscripten di Docker
Pada bagian pertama, kami mengkompilasi FFmpeg dengan gcc dan dapat beralih ke menggunakan gambar Docker dengan emscripten.
Saya akan menggunakan trzeci / emscripten versi 1.38.45:
$ docker pull trzeci/emscripten:1.38.45
Karena gambar membutuhkan sekitar 1 GB, prosesnya mungkin memakan waktu.
Sekarang kita akan menemukan konfigurasi yang benar untuk mengkompilasi FFmpeg ke emscripten dengan coba-coba, yang akan membutuhkan ketekunan dan membaca volume besar dokumentasi. Jalankan wadah dengan emscripten dan pasang sumber FFmpeg di direktori / src .
# , FFmpeg $ docker run -it \ -v $PWD:/src \ trzeci/emscripten:1.38.45 \ /bin/bash
Di dalam wadah, jalankan ls --color untuk melihat sesuatu seperti ini:
Menggunakan emconfigure dan emmake . Bagaimana mengatasi masalah kompilasi
Mari kita mulai dengan konfigurasi. Pada bagian pertama, kami melakukan ./configure --disable-x86asm , dalam emscripten ini dicapai dengan emconfigure ./configure --disable-x86asm perintah . (Untuk detail tentang penggunaan emconfigure, lihat di sini )
$ emconfigure ./configure --disable-x86asm
Dan karena kita tidak melihat kesalahan, itu tetap hanya untuk menjalankan emmake make -j4 dan mendapatkan FFmpeg.js yang didambakan? Sayangnya tidak. Salah satu tugas terpenting untuk emconfigure adalah mengganti compiler gcc dengan emcc (atau g ++ dengan em ++), tetapi hasil ./configure masih menghasilkan gcc.
root@57ab95def750:/src# emconfigure ./configure --disable-x86asm emscripten sdl2-config called with /emsdk_portable/emscripten/tag-1.38.45/system/bin/sdl2-config --cflags emscripten sdl2-config called with /emsdk_portable/emscripten/tag-1.38.45/system/bin/sdl2-config --libs install prefix /usr/local source path . C compiler gcc # emcc C library glibc ARCH x86 (generic) big-endian no runtime cpu detection yes standalone assembly no x86 assembler nasm
Otomatisasi apa pun memiliki batasnya, dan dalam hal ini, sayangnya, kita harus melakukan semuanya secara manual. Mari kita lihat apakah ada argumen untuk membantu kami:
$ ./configure --help
Di bawah bagian opsi Toolchain , kita melihat argumen untuk menunjukkan jenis kompiler.
root@57ab95def750:/src# ./configure --help Usage: configure [options] Options: [defaults in brackets after descriptions]Help options: ... Toolchain options: ... --nm=NM use nm tool NM [nm -g] --ar=AR use archive tool AR [ar] --as=AS use assembler AS [] --ln_s=LN_S use symbolic link tool LN_S [ln -s -f] --strip=STRIP use strip tool STRIP [strip] --windres=WINDRES use windows resource compiler WINDRES [windres] --x86asmexe=EXE use nasm-compatible assembler EXE [nasm] --cc=CC use C compiler CC [gcc] --cxx=CXX use C compiler CXX [g++] --objcc=OCC use ObjC compiler OCC [gcc] --dep-cc=DEPCC use dependency generator DEPCC [gcc] --nvcc=NVCC use Nvidia CUDA compiler NVCC [nvcc] --ld=LD use linker LD [] ...
Mari kita gunakan di emscripten
$ emconfigure ./configure \ --disable-x86asm \ --nm="llvm-nm -g" \ --ar=emar \ --cc=emcc \ --cxx=em++ \ --objcc=emcc \ --dep-cc=emcc
Sekarang mengeksekusi ./configure akan membutuhkan lebih banyak waktu, tetapi sebagai hasilnya kita mendapatkan emcc.
root@57ab95def750:/src# emconfigure ... emscripten sdl2-config called with /emsdk_portable/emscripten/tag-1.38.45/system/bin/sdl2-config --cflags emscripten sdl2-config called with /emsdk_portable/emscripten/tag-1.38.45/system/bin/sdl2-config --libs install prefix /usr/local source path . C compiler emcc # emcc C library ARCH x86 (generic) big-endian no runtime cpu detection yes standalone assembly no
Mari kita lihat bagaimana kompilasi berjalan.
$ emmake make -j4
Dan segera sebuah kesalahan ...
root@57ab95def750:/src# emmake make -j4 ... ./libavutil/x86/timer.h:39:24: error: invalid output constraint '=a' in asm : "=a" (a), "=d" (d)); ^
Pesan tersebut menunjukkan bahwa kesalahan tersebut terkait dengan asm. Buka ./libavutil/x86/timer.h untuk melihat bahwa masalahnya ada di assembler inline x86, yang tidak kompatibel dengan WebAssembly, jadi matikan.
$ emconfigure ./configure \ --disable-x86asm \ --disable-inline-asm \ # asm --nm="llvm-nm -g" \ --ar=emar \ --cc=emcc \ --cxx=em++ \ --objcc=emcc \ --dep-cc=emcc
Ayo coba kompilasi lagi.
$ emmake make -j4
Kompilasi berlanjut sampai kesalahan berikutnya.
root@57ab95def750:/src# emmake make -j4 ... AR libavdevice/libavdevice.a AR libavfilter/libavfilter.a AR libavformat/libavformat.a AR libavcodec/libavcodec.a AR libswresample/libswresample.a AR libswscale/libswscale.a AR libavutil/libavutil.a HOSTLD doc/print_options GENTEXI doc/avoptions_format.texi /bin/sh: 1: doc/print_options: Exec format error doc/Makefile:59: recipe for target 'doc/avoptions_format.texi' failed make: *** [doc/avoptions_format.texi] Error 2 make: *** Waiting for unfinished jobs....
Sesuatu yang berkaitan dengan pembuatan dokumentasi, yang sama sekali tidak kita butuhkan, jadi matikan saja.
$ emconfigure ./configure \ --disable-x86asm \ --disable-inline-asm \ --disable-doc \ # --nm="llvm-nm -g" \ --ar=emar \ --cc=emcc \ --cxx=em++ \ --objcc=emcc \ --dep-cc=emcc
Kami melakukannya lagi.
$ emmake make -j4
Sekarang kesalahan telah terjadi pada tahap strip.
root@57ab95def750:/src# emmake make -j4 ... STRIP ffmpeg STRIP ffprobe strip:ffmpeg_g: File format not recognized strip:ffprobe_g: File format not recognized Makefile:101: recipe for target 'ffmpeg' failed make: *** [ffmpeg] Error 1 make: *** Waiting for unfinished jobs.... Makefile:101: recipe for target 'ffprobe' failed make: *** [ffprobe] Error 1
Karena pemangkasan asli tidak kompatibel dengan versi WebAssembly kami, kami juga akan menonaktifkannya.
$ emconfigure ./configure \ --disable-x86asm \ --disable-inline-asm \ --disable-doc \ --disable-stripping \ # strip --nm="llvm-nm -g" \ --ar=emar \ --cc=emcc \ --cxx=em++ \ --objcc=emcc \ --dep-cc=emcc
Usaha keempat.
$ emmake make -j4
Akhirnya, proses berakhir tanpa kesalahan. Tetapi hanya pada output kita mendapatkan file ffmpeg , yang tidak dimulai, dan itu bukan file js (atau file wasm). Untuk mendapatkan file js, kita perlu menambahkan -o ffmpeg.js ke perintah emcc, yang dapat dilakukan dengan dua cara:
- Ubah Makefile dari FFmpeg itu sendiri
- Tambahkan kompilasi / penautan tambahan
Kami akan memilih cara kedua, karena saya tidak ingin menyentuh sumber FFmpeg karena kemungkinan efek samping. Jadi kami menemukan bagaimana ffmpeg dihasilkan menggunakan make. Di sinilah opsi make berguna untuk menjalankan lari kering.
$ emmake make -n
Kami melihat tim generasi.
root@57ab95def750:/src# emmake make -n ... printf "LD\t%s\n" ffmpeg_g; emcc -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample -Wl,--as-needed -Wl,-z,noexecstack -Wl,--warn-common -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample -Qunused-arguments -o ffmpeg_g fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lm -pthread -lm -lm -pthread -lm -lm -lm -pthread -lm printf "CP\t%s\n" ffmpeg; cp -p ffmpeg_g ffmpeg ...
Ada banyak hal yang tidak perlu, jadi mari kita hapus argumen yang tidak digunakan (yang akan Anda lihat di akhir kompilasi), bersihkan sedikit dan ganti nama ffmpeg_g menjadi ffmpeg.js .
$ emcc \ -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample \ -Qunused-arguments \ -o ffmpeg.js fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o \ -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lm -pthread
Seharusnya berhasil, tetapi kita akan mengalami masalah kurangnya memori.
root@57ab95def750:/src# emcc ... shared:ERROR: Memory is not large enough for static data (11794000) plus the stack (5242880), please increase TOTAL_MEMORY (16777216) to at least 17037904
Tambahkan argumen TOTAL_MEMORY untuk menambah ukuran memori (33554432 Bytes: = 32 MB).
$ emcc \ -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample \ -Qunused-arguments \ -o ffmpeg.js fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o \ -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lm -pthread \ -s TOTAL_MEMORY=33554432
Akhirnya kami mendapat file js dan wasm kami
root@57ab95def750:/src# ls ffmpeg* ffmpeg ffmpeg.js ffmpeg.js.mem ffmpeg.wasm ffmpeg.worker.js ffmpeg_g
Buat test.html untuk menguji FFmpeg.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="./ffmpeg.js"></script> </head> <body> </body> </html>
Mari kita mulai server yang mudah (dengan menjalankan python2 -m SimpleHTTPServer ) dan membuka halaman yang dihasilkan ( http: // localhost: 8000 / test.html ) , lalu buka Chrome DevTools.
Seperti yang Anda lihat, FFmpeg bekerja setengah dengan dosa, jadi sekarang Anda dapat mulai memoles ffmpeg.js.
Skrip build lengkap dapat ditemukan di repositori ini (build-with-docker.sh dan build-js.sh)
.