Az elmúlt néhány napban kénytelen voltam némi node.js tudást magamra szedni, hogy megoldjak egy aranyos problémát: hogyan alakítsunk át egy zenefájlt “lekérdezés közben” egy “szerver nélkül”, felhőben futó függvény segítségével. Nem olyan egyszerű…
Miért is? Miért nem jó simán írni egy “vékony”, gyors szervert, mondhatni microservice-t? Jó az is. (Meg is volt.) A cloud function viszont jobb lehet. Ami itt most fontos lehet: más a számlázási modellje, illetve jobban skálázható. Csakhát kicsit még vadnyugat a viszonylag kényelmes szerverkód-hegesztéshez képest.
A nehezítések (a g-betűs szekta megoldásánál legalább is :p ):
- A function nem menthet semmit lokálisan, tehát pl. kizárhatjuk, hogy lementsük az eredeti fájlt, és átküldjük egy normál ffmpeg-en.
- A lokális tesztelés enyhén szólva is nem egyszerű. (Mint utólag kiderült, nem is pontos…)
- Csak a node.js támogatott… (legalább tanultam valami újat a héten)
A fájl módosítások nélküli továbbküldése a backendtől a hívó felé meglehetősen egyszerű, simán csak “pipe-olhatjuk” (csövezhetjük! 😀 ) a bejövő választ:
index.js
exports.getMedia = (req, res) => { request('http_request_url') .pipe(res); };
Innentől jön a neheze. Elviekben az átalakításhoz szükséges fájlok (tehát pl maga az ffmpeg) telepíthető a functionnel együtt, de mivel nem lehet írni, csak olvasni a function alatti tárolót, ezért stdin-stdouttal kellene megoldani az egészet. (Vagy esetleg valamilyen named pipe-pal, de az már csak hab lenne a tortán.)
Jó pár lehetséges megoldás kipróbálása után végül is az alábbi bizonyult működőképesnek.
index.js
const request = require('request'); const ffmpeg = require('ffmpeg-stream').ffmpeg; exports.getMedia = (req, res) => { var converter = ffmpeg(); var input = converter.input({f: 'flac'}); request('http_request_url') .pipe(input); converter.output({f: 'oga', acodec: 'libvorbis'}) .pipe(res); converter.run(); };
Az ffmpeg az ffmpeg-stream node package-ből származik. Annyi hátránya van, hogy telepíteni kell mellé az ffmpeget is, ami a cloud function esetében kicsit nehézkes: mivel a functionnél nincs lehetőségünk telepíteni bármit is, a functionnel együtt fel kell tölteni a binárisokat is. Ezen kívül pedig beállítani egy környezeti változót (magyarabbul: env var), hogy a node package megtalálja az ffmpeget. Bővebben a package repójában.
A teljesség kedvéért itt a package.json tartalma is:
package.json
{ "name": "test", "version": "0.0.1", "dependencies": { "request": "^2.81.0", "ffmpeg-stream": "0.5.0" } }
A még nagyobb teljesség kedvéért pedig alant egy példa arról, hogy mit kell kiállnia annak, aki node-ban fejleszt. 😀
A kaland folytatódik…