HLS dalam MP4 menggunakan ffmpeg di browser

Halo! Selama lebih dari dua bulan, di waktu senggang saya telah melihat aplikasi web untuk mengkonversi HLS dan DASH ke MP4 menggunakan emscripten dan ffmpeg, dari mana saya ingin berbagi bagaimana saya berhasil melakukan ini.

Dalam artikel ini saya tidak akan mengutip kode sumber dari ffmpeg dan tambalan, seperti kebanyakan dari mereka dilakukan di atas lutut saya, dan saya tidak pandai C. Tapi sekarang ada artikel yang cukup untuk membantu Anda.

pengantar


Dua tahun yang lalu saya memiliki tujuan untuk menggabungkan track audio dan video menjadi satu file mp4. Lalu saya hanya terjun ke emscripten dan untuk dasar-dasarnya saya menemukan repositori ffmpeg.js dari mana saya belajar banyak. Kemudian saya hampir dapat mencapai tujuan, walaupun saya berorientasi kondisional dalam C.
Memahami kode sumber, ffmpeg membuat tambalan untuk bekerja dengan sistem file, di mana membaca dari file menyebabkan fungsi asinkron di js dari mana saya membaca gumpalan file dan mentransfer buffer, dan ketika menulis dipanggil Fungsi js yang mengirim data buffer ke repositori.

Tetapi ada masalah dengan fungsi asinkron, yang saya tidak bisa pecahkan dengan benar, mereka bekerja melalui asyncify (fastcomp), yang tidak berfungsi dengan benar dalam beberapa kasus, yaitu, eksekusi kode dalam wasm tidak berhenti, tanpa menunggu hasil dari fungsi js, itu saja hancur. Masalah ini diperbaiki melalui flag EMTERPRETIFY_WHITELIST, yang tampaknya memindahkan kode dari wasm ke asm pada saat yang sama dan memperlambatnya, dan perlu untuk men-debug tumpukan panggilan dan menambahkan fungsi yang rusak ke daftar dengan setiap pengecualian.

Secara umum, dengan masalah seperti itu, ini tidak bisa disebut solusi kerja, di mana semua ini tetap merupakan demo kecil.



Satu setengah tahun kemudian


Setelah menonton laporan di Google Dev Summit tentang fitur-fitur baru di WebAssambly , saya pergi untuk melihat bagaimana emscripten lakukan dan melihat pesan:
Emscripten memancarkan WebAssembly menggunakan backend LLVM wasm hulu, karena versi 1.39.0 (Oktober 2019), dan backend fastcomp lama tidak digunakan lagi

Saya ingin mencoba membangun kembali format repacker saya. Sekitar seminggu saya mencari cara untuk memperbaiki masalah kompilasi baru dan akhirnya menyatukan semuanya. Perubahannya tidak banyak, tapi itu bukan karena linker perpustakaan baru, dan sudah putus asa untuk mengumpulkan setidaknya sesuatu, saya baru saja melihat perpustakaan yang bermasalah (ternyata, perpustakaan itu sendiri terhubung dan Anda tidak perlu menentukannya dengan tangan Anda saat perakitan).

Dan sekarang, saatnya telah tiba ketika ia telah mengumpulkan dan menghasilkan! Masalah dengan kode asinkron hilang, tidak perlu men-debug apa pun, itu berfungsi sebagaimana mestinya dari awal.

Di sini saya tampaknya telah mencapai tujuan saya, tetapi ... yang baru muncul.

Tulis ulang Protokol HTTP


Pemikiran seperti itu sudah ada sejak lama. Ini memungkinkan Anda untuk mengunduh HLS atau DASH, dan tidak hanya daftar putar yang sudah jadi tetapi juga streaming langsung. Dan saya belum pernah melihat yang seperti ini di Internet.

Butuh waktu sekitar tiga minggu untuk membuat setidaknya sesuatu bekerja dengan saya dengan istirahat pendek. Saya tahu C (walaupun tidak memiliki pengalaman), ada banyak masalah dengan pointer (sulit untuk melacak ke mana perginya, dan bahkan dalam kode orang lain), tetapi pada akhirnya sesuatu dikompilasi tanpa kesalahan. Setelah kesuksesan pertama, ini bahkan memberi lebih banyak antusiasme untuk menyelesaikan gagasan itu.

Hanya beberapa minggu, dan akhirnya saya berhasil melakukan iterasi pertama dari protokol http yang berfungsi, dan sepertinya itu saja?

Ketika yang paling sulit berakhir


Pada titik ini, saya memiliki kerangka kerja siap, bentuk html kecil dengan bidang input url dan tombol mulai, pada dasarnya itu berhasil. Tapi itu masih perlu untuk menulis ekstensi untuk memotong CORS dan memuat data, membuat penyimpanan yang akan menulis data dalam potongan, membuat antarmuka dengan tampilan kemajuan, semua ini sudah di-debug untuk memperbaiki masalah di browser yang berbeda. Secara umum, waktunya telah tiba akhirnya memungkinkan untuk menggunakannya.

Pada dasarnya, skrip pengguna dibuat, yang merupakan proksi untuk mengambil permintaan dari ffmpeg untuk mengunduh data.

Beberapa hari kemudian, ekstensi untuk Chrome dan Firefox sudah siap, yang menggunakan webRequest mengumpulkan semua tautan hls yang dimuat browser saat menonton video.

Di Firefox, ternyata, API ekstensi tidak memungkinkan Anda untuk mengelola daya, dari mana Anda tidak dapat mencegah komputer tertidur, sayangnya.

Ekstensinya terlihat seperti ini:



Baru saja memperbaiki halaman tempat situs itu sedikit, mengacaukan material-ui, menyelesaikan semua tempat yang dihancurkan.



Setelah menguji berbagai cara menyimpan data, saya mengungkapkan sejumlah masalah:

Blob - Chrome menulisnya ke RAM dan jatuh ke disk ketika meluap, tetapi hanya di OSX ketika memori meluap, OS meninggalkan akun dan menutup semua aplikasi yang terbuka. Dan Firefox umumnya selalu menyimpan data dalam memori.

Penyimpanan cache- berfungsi seperti IndexedDb, tetapi setelah menulis data, di Chrome blob mereka tetap di RAM (baik bug atau fitcha), tetapi ternyata data ditulis ke penyimpanan cache (ke disk) dan juga turun sama ketika memori penuh volume ke disk sebagai gumpalan.

IndexedDb - bekerja seperti jam, tahu cara menyimpan gumpalan, menulis data tanpa embel-embel, tetapi Firefox secara ketat membatasi jumlah 2gb.

Saya bekerja sedikit, saya berhasil membuat fungsi mengganggu proses ffmpeg (melalui pointer), saya datang dengan cara membuat pilihan format (ffprobe) dan penanganan kesalahan jaringan.





Dan sekarang, Anda dapat mencoba hasilnya sendiri di sini

Bagi saya, ini adalah hal yang sangat diperlukan ketika Anda perlu merekam streaming di tweet atau mengunduh VOD. Ini juga bekerja dengan laptop, mixer, dan situs lain yang menyiarkan konten dalam HLS atau DASH (sayangnya, implementasi DASH di ffmpeg sangat kondisional dan langsung tidak dapat mengunduh dengan benar, karena tidak memperhitungkan interval permintaan fragmen).

Terima kasih telah membaca!

Jika Anda memiliki pertanyaan tentang ffmpeg dan emscripten - write, saya akan mencoba menjawab.

All Articles