WebAssembly के साथ ब्राउज़र को बढ़ाना

WebAssembly की मदद से, हम ब्राउज़र को नई सुविधाओं के साथ बेहतर बनाते हैं. इस लेख में AV1 वीडियो डिकोडर को पोर्ट करने और किसी भी मॉडर्न ब्राउज़र में AV1 वीडियो चलाने का तरीका बताया गया है.

Alex Danilo

WebAssembly के बारे में सबसे अच्छी चीज़ों में से एक है यह नई सुविधाओं के साथ योग्यता प्रयोग करना और ब्राउज़र उन सुविधाओं को मूल रूप से भेजने से पहले नए आइडिया लागू करना है (अगर ऐसा है तो भी). WebAssembly को इस तरह एक बेहतर पॉलीफ़िल मैकेनिज़्म की तरह इस्तेमाल किया जा सकता है. इसमें JavaScript के बजाय C/C++ या Rust में अपनी सुविधा लिखें.

पोर्ट करने के लिए उपलब्ध ढेरों मौजूदा कोड के साथ, ब्राउज़र में ऐसे काम किए जा सकते हैं जो WebAssembly के साथ आने तक व्यवहार करने योग्य नहीं थे.

इस लेख में, मौजूदा AV1 वीडियो कोडेक के सोर्स कोड को इस्तेमाल करने, उसके लिए एक रैपर बनाने, उसे अपने ब्राउज़र में आज़माने, और रैपर को डीबग करने के लिए टेस्ट हार्नेस बनाने के बारे में सलाह दी गई है. यहां दिए गए उदाहरण का पूरा सोर्स कोड, रेफ़रंस के लिए github.com/GoogleChromeLabs/vasm-av1 पर उपलब्ध है.

इन दो 24 FPS (फ़्रेम प्रति सेकंड) की वीडियो फ़ाइलों की जांच करने वाली फ़ाइल डाउनलोड करें और उन्हें हमारे बनाए गए डेमो पर आज़माएं.

कोई दिलचस्प कोड-बेस चुनना

पिछले कई सालों से, हमने देखा है कि वेब पर बड़ी संख्या में ट्रैफ़िक वीडियो डेटा का होता है. हालांकि, Cisco इसका अनुमान लगाता है कि असल में यह 80% है! ब्राउज़र वेंडर और वीडियो साइटों को पता है कि इस तरह के वीडियो कॉन्टेंट को खर्च होने वाला डेटा कम करना है. इसके लिए सही है, बेहतर कंप्रेशन. साथ ही, यह भी है कि अगली-पीढ़ी की टेक्नोलॉजी के वीडियो कंप्रेस करने के बारे में काफ़ी रिसर्च की जा रही है. इसका मकसद, इंटरनेट पर वीडियो शिपिंग के लिए डेटा की बोझ को कम करना है.

हालांकि, Alliance for Open Media, अगली-पीढ़ी की वीडियो कंप्रेशन स्कीम पर काम कर रहा है. इस स्कीम को AV1 कहते हैं. इसमें वीडियो के डेटा को काफ़ी कम करने का वादा किया जाता है. आने वाले समय में, हम ब्राउज़र से AV1 के लिए नेटिव सपोर्ट मिलने की उम्मीद कर सकते हैं. हालांकि, अच्छी बात यह है कि कंप्रेसर और डिकंप्रेसर के लिए सोर्स कोड ओपन सोर्स हैं. इससे इसे WebAssembly में कंपाइल करने की कोशिश करने वाला सबसे अच्छा विकल्प है, ताकि हम ब्राउज़र में इसके साथ प्रयोग कर सकें.

बनी फ़िल्म की इमेज.

ब्राउज़र में इस्तेमाल के हिसाब से ढालना

ब्राउज़र में इस कोड को डालने के लिए, हमें सबसे पहले मौजूदा कोड के बारे में जानना होगा, ताकि यह पता चल सके कि एपीआई कैसा है. इस कोड को पहली बार देखें, तो दो चीज़ें सबसे अलग होती हैं:

  1. सोर्स ट्री को cmake नाम के टूल का इस्तेमाल करके बनाया गया है; और
  2. ऐसे कई उदाहरण हैं जिनमें शामिल सभी में किसी तरह का फ़ाइल-आधारित इंटरफ़ेस होता है.

डिफ़ॉल्ट रूप से बनाए गए सभी उदाहरण कमांड लाइन पर चलाए जा सकते हैं. कम्यूनिटी में मौजूद कई अन्य कोड बेस पर भी ऐसा किया जा सकता है. इसलिए, इसे ब्राउज़र में चलाने के लिए हम जो इंटरफ़ेस बनाने जा रहे हैं वह कई दूसरे कमांड लाइन टूल के लिए काम का हो सकता है.

सोर्स कोड बनाने के लिए, cmake का इस्तेमाल किया जा रहा है

अच्छी बात यह है कि AV1 के लेखक Emscripten के साथ प्रयोग कर रहे हैं. यह एक ऐसा SDK टूल है जिसका इस्तेमाल हम अपना WebAssembly वर्शन बनाने के लिए करेंगे. AV1 रिपॉज़िटरी के रूट में, फ़ाइल CMakeLists.txtमें ये बिल्ड नियम शामिल हैं:

if(EMSCRIPTEN)
add_preproc_definition(_POSIX_SOURCE)
append_link_flag_to_target("inspect" "-s TOTAL_MEMORY=402653184")
append_link_flag_to_target("inspect" "-s MODULARIZE=1")
append_link_flag_to_target("inspect"
                            "-s EXPORT_NAME=\"\'DecoderModule\'\"")
append_link_flag_to_target("inspect" "--memory-init-file 0")

if("${CMAKE_BUILD_TYPE}" STREQUAL "")
    # Default to -O3 when no build type is specified.
    append_compiler_flag("-O3")
endif()
em_link_post_js(inspect "${AOM_ROOT}/tools/inspect-post.js")
endif()

Emscripten टूलचेन दो फ़ॉर्मैट में आउटपुट जनरेट कर सकता है. एक का नाम asm.js है और दूसरे का WebAssembly. हम WebAssembly को टारगेट करेंगे, क्योंकि यह कम आउटपुट देती है और ज़्यादा तेज़ी से काम कर सकती है. बिल्ड के इन मौजूदा नियमों का मकसद लाइब्रेरी के asm.js वर्शन को कंपाइल करना है, ताकि जांच करने वाले ऐप्लिकेशन में उसका इस्तेमाल किया जा सके. इसका इस्तेमाल वीडियो फ़ाइल के कॉन्टेंट को देखने के लिए किया जाता है. हमारे इस्तेमाल के लिए हमें WebAssembly आउटपुट की ज़रूरत है, ताकि हम ऊपर दिए गए नियमों में बताए गए endif()स्टेटमेंट के बंद होने से ठीक पहले इन पंक्तियों को जोड़ दें.

# Force generation of Wasm instead of asm.js
append_link_flag_to_target("inspect" "-s WASM=1")
append_compiler_flag("-s WASM=1")

cmake की मदद से बनाने का मतलब है कि सबसे पहले कुछ Makefiles जनरेट करने के लिए, cmake खुद चलाकर देखें. इसके बाद, make निर्देश को चलाएं. इससे, कंपाइलेशन चरण पूरा होगा. ध्यान दें कि हम Emscripten का इस्तेमाल कर रहे हैं, इसलिए हमें डिफ़ॉल्ट होस्ट कंपाइलर के बजाय Emscripten कंपाइलर टूलचेन का इस्तेमाल करना होगा. इसके लिए, Emscripten.cmake का इस्तेमाल किया जाता है, जो Emscripten SDK टूल का हिस्सा है. इसके पाथ को पैरामीटर के तौर पर cmake में भी पास किया जाता है. नीचे दी गई कमांड लाइन का इस्तेमाल, हम मेकफ़ाइल जनरेट करने के लिए करते हैं:

cmake path/to/aom \
  -DENABLE_CCACHE=1 -DAOM_TARGET_CPU=generic -DENABLE_DOCS=0 \
  -DCONFIG_ACCOUNTING=1 -DCONFIG_INSPECTION=1 -DCONFIG_MULTITHREAD=0 \
  -DCONFIG_RUNTIME_CPU_DETECT=0 -DCONFIG_UNIT_TESTS=0
  -DCONFIG_WEBM_IO=0 \
  -DCMAKE_TOOLCHAIN_FILE=path/to/emsdk-portable/.../Emscripten.cmake

पैरामीटर path/to/aom को AV1 लाइब्रेरी की सोर्स फ़ाइलों के पूरे पाथ पर सेट किया जाना चाहिए. Emscripten.cmake Toolchain की जानकारी वाली फ़ाइल के पाथ पर path/to/emsdk-portable/…/Emscripten.cmake पैरामीटर को सेट करना ज़रूरी है.

सुविधा के लिए हम उस फ़ाइल का पता लगाने के लिए शेल स्क्रिप्ट का उपयोग करते हैं:

#!/bin/sh
EMCC_LOC=`which emcc`
EMSDK_LOC=`echo $EMCC_LOC | sed 's?/emscripten/[0-9.]*/emcc??'`
EMCMAKE_LOC=`find $EMSDK_LOC -name Emscripten.cmake -print`
echo $EMCMAKE_LOC

अगर इस प्रोजेक्ट के लिए टॉप-लेवल Makefile देखें, तो आपको यह पता चलेगा कि बिल्ड को कॉन्फ़िगर करने के लिए उस स्क्रिप्ट का इस्तेमाल कैसे किया जाता है.

अब पूरा सेटअप पूरा हो गया है, तो हम सिर्फ़ make को कॉल करते हैं, जिससे सैंपल के साथ पूरा सोर्स ट्री बनाया जाएगा. हालांकि, सबसे ज़्यादा ज़रूरी तरीके से libaom.a जनरेट किया जाता है. इसमें वीडियो डिकोडर इकट्ठा किया जाता है और उसे अपने प्रोजेक्ट में शामिल किया जा सकता है.

लाइब्रेरी में इंटरफ़ेस दिखाने के लिए एपीआई डिज़ाइन करना

लाइब्रेरी बनाने के बाद, हमें कंप्रेस किए गए वीडियो डेटा को भेजने के लिए इसे इंटरफ़ेस करने के तरीके पर काम करना होगा. इसके बाद, वीडियो के उन फ़्रेम को पढ़ना होगा जिन्हें हम ब्राउज़र में दिखा सकते हैं.

AV1 कोड ट्री के अंदर एक नज़र डालें, तो एक अच्छा शुरुआती पॉइंट वीडियो डिकोडर का एक उदाहरण होता है. इसे [simple_decoder.c](https://aomedia.googlesource.com/aom/+/master/examples/simple_decoder.c) फ़ाइल में देखा जा सकता है. वह डिकोडर आईवीएफ़ फ़ाइल में पढ़ता है और उसे वीडियो में फ़्रेम को दिखाने वाली इमेज की सीरीज़ में डिकोड करता है.

हम सोर्स फ़ाइल में अपना इंटरफ़ेस लागू करते हैं [decode-av1.c](https://github.com/GoogleChromeLabs/wasm-av1/blob/master/decode-av1.c).

हमारा ब्राउज़र, फ़ाइल सिस्टम की फ़ाइलें नहीं पढ़ सकता. इसलिए, हमें कुछ ऐसा इंटरफ़ेस डिज़ाइन करना होगा जिससे हम अपने I/O को अलग कर सकें. इससे हम अपनी AV1 लाइब्रेरी में डेटा पाने के लिए, उदाहरण डिकोडर की तरह ही कुछ बना सकेंगे.

कमांड लाइन में, फ़ाइल I/O को स्ट्रीम इंटरफ़ेस कहा जाता है. इसलिए, हम सिर्फ़ अपना खुद का इंटरफ़ेस बना सकते हैं, जो स्ट्रीम I/O जैसा दिखता है. साथ ही, हम बुनियादी तौर पर लागू करने की प्रोसेस में जो चाहें उसे बना सकते हैं.

हम अपने इंटरफ़ेस को इस तरह परिभाषित करते हैं:

DATA_Source *DS_open(const char *what);
size_t      DS_read(DATA_Source *ds,
                    unsigned char *buf, size_t bytes);
int         DS_empty(DATA_Source *ds);
void        DS_close(DATA_Source *ds);
// Helper function for blob support
void        DS_set_blob(DATA_Source *ds, void *buf, size_t len);

open/read/empty/close फ़ंक्शन काफ़ी हद तक सामान्य फ़ाइल I/O कार्रवाइयों जैसे दिखते हैं. इनकी मदद से, हम किसी कमांड लाइन ऐप्लिकेशन के लिए फ़ाइल I/O पर उन्हें आसानी से मैप कर सकते हैं या ब्राउज़र में रन करने पर उन्हें किसी दूसरी तरह से लागू कर सकते हैं. DATA_Source टाइप, JavaScript साइड से ओपेक नहीं होता. साथ ही, यह सिर्फ़ इंटरफ़ेस को इनकैप्सुलेट करने का काम करता है. ध्यान दें कि फ़ाइल सिमैंटिक पर ध्यान देने वाला एपीआई बनाने से, कई दूसरे कोड-बेस में फिर से इस्तेमाल करना आसान हो जाता है जिनका इस्तेमाल कमांड लाइन से किया जा सकता है (जैसे, diff, sed वगैरह).

हमें DS_set_blob नाम का एक हेल्पर फ़ंक्शन भी तय करना होगा, जो रॉ बाइनरी डेटा को हमारे स्ट्रीम I/O फ़ंक्शन से जोड़ता है. इससे ब्लॉब को इस तरह 'पढ़ना' मिल जाता है, जैसे वह कोई स्ट्रीम है (यानी क्रम से पढ़ी गई फ़ाइल की तरह दिखता है).

लागू करने के हमारे उदाहरण की मदद से, पास किए गए ब्लॉब में पास किए गए डेटा को इस तरह से पढ़ा जा सकता है कि वह क्रम में पढ़ा गया डेटा सोर्स हो. रेफ़रंस कोड blob-api.c फ़ाइल में मिल सकता है. इसे पूरा लागू करने का तरीका सिर्फ़ यही है:

struct DATA_Source {
    void        *ds_Buf;
    size_t      ds_Len;
    size_t      ds_Pos;
};

DATA_Source *
DS_open(const char *what) {
    DATA_Source     *ds;

    ds = malloc(sizeof *ds);
    if (ds != NULL) {
        memset(ds, 0, sizeof *ds);
    }
    return ds;
}

size_t
DS_read(DATA_Source *ds, unsigned char *buf, size_t bytes) {
    if (DS_empty(ds) || buf == NULL) {
        return 0;
    }
    if (bytes > (ds->ds_Len - ds->ds_Pos)) {
        bytes = ds->ds_Len - ds->ds_Pos;
    }
    memcpy(buf, &ds->ds_Buf[ds->ds_Pos], bytes);
    ds->ds_Pos += bytes;

    return bytes;
}

int
DS_empty(DATA_Source *ds) {
    return ds->ds_Pos >= ds->ds_Len;
}

void
DS_close(DATA_Source *ds) {
    free(ds);
}

void
DS_set_blob(DATA_Source *ds, void *buf, size_t len) {
    ds->ds_Buf = buf;
    ds->ds_Len = len;
    ds->ds_Pos = 0;
}

ब्राउज़र के बाहर टेस्ट करने के लिए टेस्ट हार्नेस बनाना

सॉफ़्टवेयर इंजीनियरिंग में सबसे सही तरीकों में से एक है, इंटिग्रेशन टेस्ट के साथ कोड के लिए यूनिट टेस्ट तैयार करना.

ब्राउज़र में WebAssembly के साथ काम करते समय, हम जिस कोड पर काम कर रहे हैं उसके इंटरफ़ेस के लिए कुछ यूनिट टेस्ट बनाना सही रहेगा. इससे हम ब्राउज़र के बाहर डीबग कर सकते हैं और हमारे बनाए हुए इंटरफ़ेस की जांच भी कर सकते हैं.

इस उदाहरण में हम AV1 लाइब्रेरी के इंटरफ़ेस के तौर पर, स्ट्रीम पर आधारित एपीआई को एम्युलेट कर रहे हैं. इसलिए, तर्क के साथ एक टेस्ट हार्नेस बनाना सही होता है, जिसका इस्तेमाल हम अपने एपीआई का ऐसा वर्शन बनाने के लिए कर सकते हैं जो कमांड लाइन पर चलता हो और अपने DATA_Source एपीआई के नीचे फ़ाइल I/O को लागू करके, हुड के तहत असल I/O फ़ाइल करता हो.

हमारे टेस्ट हार्नेस का स्ट्रीम I/O कोड आसान है और यह ऐसा दिखता है:

DATA_Source *
DS_open(const char *what) {
    return (DATA_Source *)fopen(what, "rb");
}

size_t
DS_read(DATA_Source *ds, unsigned char *buf, size_t bytes) {
    return fread(buf, 1, bytes, (FILE *)ds);
}

int
DS_empty(DATA_Source *ds) {
    return feof((FILE *)ds);
}

void
DS_close(DATA_Source *ds) {
    fclose((FILE *)ds);
}

स्ट्रीम इंटरफ़ेस को ऐब्स्ट्रैक्ट करके, हम अपना WebAssembly मॉड्यूल बना सकते हैं. इससे, ब्राउज़र में होते समय बाइनरी डेटा ब्लॉब का इस्तेमाल किया जा सकता है. साथ ही, कमांड लाइन से जांच करने के लिए कोड बनाते समय, हम असल फ़ाइलों के लिए इंटरफ़ेस का इस्तेमाल कर सकते हैं. टेस्ट हार्नेस का हमारा कोड, सोर्स फ़ाइल test.c के उदाहरण में मिल सकता है.

एक से ज़्यादा वीडियो फ़्रेम के लिए बफ़रिंग सिस्टम लागू करना

वीडियो चलाते समय बेहतर क्वालिटी में वीडियो चलाने के लिए कुछ फ़्रेम बफ़र करना आम बात है. अपने मकसद के लिए, हम वीडियो के 10 फ़्रेम का बफ़र लागू करेंगे, ताकि वीडियो चलाना शुरू करने से पहले हम 10 फ़्रेम का बफ़र कर दें. इसके बाद, जब भी कोई फ़्रेम दिखाया जाएगा, तब हम दूसरे फ़्रेम को डिकोड करने की कोशिश करेंगे, ताकि हम बफ़र को पूरा रख सकें. इस तरीके से यह पक्का किया जाता है कि वीडियो में फ़्रेम पहले से मौजूद हैं, ताकि वीडियो को स्टट्रिंग से रोका जा सके.

हमारे आसान उदाहरण से, कंप्रेस किया गया पूरा वीडियो पढ़ा जा सकता है. इसलिए, बफ़रिंग की ज़रूरत नहीं है. हालांकि, अगर हमें सर्वर के स्ट्रीमिंग इनपुट के साथ काम करने के लिए सोर्स डेटा इंटरफ़ेस बढ़ाना है, तो हमें बफ़रिंग सिस्टम की ज़रूरत होगी.

AV1 लाइब्रेरी से वीडियो डेटा के फ़्रेम पढ़ने और बफ़र में सेव करने के लिए, decode-av1.c में दिया गया कोड:

void
AVX_Decoder_run(AVX_Decoder *ad) {
    ...
    // Try to decode an image from the compressed stream, and buffer
    while (ad->ad_NumBuffered < NUM_FRAMES_BUFFERED) {
        ad->ad_Image = aom_codec_get_frame(&ad->ad_Codec,
                                           &ad->ad_Iterator);
        if (ad->ad_Image == NULL) {
            break;
        }
        else {
            buffer_frame(ad);
        }
    }


हमने बफ़र में वीडियो के 10 फ़्रेम शामिल करने का विकल्प चुना है, जो कि सिर्फ़ एक मध्यस्थता है. ज़्यादा फ़्रेम बफ़र होने का मतलब है कि वीडियो शुरू होने में ज़्यादा इंतज़ार करना पड़ता है, जबकि बहुत कम फ़्रेम बफ़र होने की वजह से प्लेबैक के दौरान रुक सकता है. नेटिव ब्राउज़र को लागू करने पर, फ़्रेम का बफ़र होना, इस प्रोसेस को लागू करने के तरीके से कहीं ज़्यादा मुश्किल है.

WebGL की मदद से पेज पर वीडियो फ़्रेम पाना

वीडियो के जो फ़्रेम हमने बफ़र किए हैं उन्हें हमारे पेज पर दिखाना ज़रूरी है. क्योंकि यह लगातार बदलने वाला वीडियो कॉन्टेंट है, इसलिए हम जितनी जल्दी हो सके यह करना चाहते हैं. इसके लिए, हम WebGL का इस्तेमाल करते हैं.

WebGL, हमें वीडियो के फ़्रेम जैसी एक चित्र लेने देता है, और उसे एक ऐसी बनावट के रूप में उपयोग करने देता है जिस पर ज्यामिति पर पेंट किया जाता है. WebGL की दुनिया में, हर चीज़ त्रिभुजों से मिलकर बनी है. इसलिए, हमारे मामले में हम WebGL की पहले से मौजूद एक सुविधाजनक सुविधा का इस्तेमाल कर सकते हैं, जिसे gl.TRIANGLE_FAN कहा जाता है.

हालांकि, एक छोटी सी समस्या है. WebGL टेक्सचर एक आरजीबी इमेज, एक बाइट प्रति कलर चैनल होना चाहिए. हमारे AV1 डिकोडर से मिलने वाला आउटपुट एक YUV फ़ॉर्मैट वाली इमेज है, जिसमें डिफ़ॉल्ट आउटपुट हर चैनल के लिए 16 बिट होता है. साथ ही, हर U या V वैल्यू, असल आउटपुट इमेज में 4 पिक्सल से मेल खाती है. इन सबका मतलब है कि हमें इमेज को डिसप्ले के लिए WebGL में भेजने से पहले उसका रंग बदलना होगा.

ऐसा करने के लिए, हम एक AVX_YUV_to_RGB() फ़ंक्शन लागू करते हैं. इसे सोर्स फ़ाइल yuv-to-rgb.c में देखा जा सकता है. वह फ़ंक्शन AV1 डिकोडर से आउटपुट को ऐसी चीज़ में बदल देता है जिसे हम WebGL में पास कर सकें. ध्यान दें, जब हम JavaScript से इस फ़ंक्शन को कॉल करते हैं, तो हमें यह पक्का करना होता है कि बदली गई इमेज को जिस मेमोरी में लिखा जा रहा है उसे WebAssembly मॉड्यूल की मेमोरी में रखा गया है. ऐसा न करने पर, उस मेमोरी को ऐक्सेस नहीं किया जा सकेगा. WebAssembly मॉड्यूल से किसी इमेज को बाहर निकालने और उसे स्क्रीन पर पेंट करने का फ़ंक्शन यह है:

function show_frame(af) {
    if (rgb_image != 0) {
        // Convert The 16-bit YUV to 8-bit RGB
        let buf = Module._AVX_Video_Frame_get_buffer(af);
        Module._AVX_YUV_to_RGB(rgb_image, buf, WIDTH, HEIGHT);
        // Paint the image onto the canvas
        drawImageToCanvas(new Uint8Array(Module.HEAPU8.buffer,
                rgb_image, 3 * WIDTH * HEIGHT), WIDTH, HEIGHT);
    }
}

WebGL पेंटिंग को लागू करने वाला drawImageToCanvas() फ़ंक्शन, रेफ़रंस के लिए सोर्स फ़ाइल draw-image.js में मिल सकता है.

आने वाले समय के लिए काम और सीखने वाली बातें

दो टेस्ट वीडियो फ़ाइलों (24 f.p.s. वीडियो के रूप में रिकॉर्ड किया जाता है) पर हमारा डेमो आज़माने से हमें कुछ चीज़ें सीखने को मिलती हैं:

  1. WebAssembly का इस्तेमाल करके, ब्राउज़र में बेहतर तरीके से चलाने के लिए एक मुश्किल कोड-बेस बनाया जा सकता है; और
  2. WebAssembly की मदद से, कंप्यूटर पर सीपीयू (CPU) वाला इंटेंसिव मोड, ऐडवांस वीडियो डिकोड करने की प्रोसेस जैसा हो सकता है.

हालांकि, इसकी कुछ सीमाएं हैं: सिर्फ़ मुख्य थ्रेड पर लागू किया जा रहा है और हम उस थ्रेड पर पेंटिंग और वीडियो डिकोड करने की प्रोसेस को इंटरलीव करते हैं. वेब वर्कर में डिकोड करने से, हमें वीडियो चलाने में आसानी हो सकती है. ऐसा इसलिए, क्योंकि फ़्रेम को डिकोड करने में लगने वाला समय, उस फ़्रेम के कॉन्टेंट पर निर्भर करता है. कभी-कभी इसमें तय सीमा से ज़्यादा समय भी लग सकता है.

WebAssembly में कंपाइल करने पर, सामान्य सीपीयू टाइप के लिए AV1 कॉन्फ़िगरेशन का इस्तेमाल किया जाता है. अगर हम सामान्य सीपीयू के लिए कमांड लाइन पर नेटिव तौर पर कंपाइल करते हैं, तो हमें WebAssembly वर्शन की तरह, वीडियो को डिकोड करने के लिए, वैसा ही सीपीयू लोड दिखता है. हालांकि, AV1 डिकोडर लाइब्रेरी में, SIMD को भी लागू किया जाता है जो पांच गुना तेज़ी से चलता है. WebAssembly कम्यूनिटी ग्रुप, फ़िलहाल सिम्ड प्रिमिटिव को शामिल करने के लिए, स्टैंडर्ड को बढ़ाने पर काम कर रहा है. इसके बाद, यह नीति को तेज़ी से डिकोड करने की प्रोसेस को तेज़ करने का वादा करेगा. ऐसा होने पर, WebAssembly वीडियो डिकोडर से रीयल-टाइम में 4K एचडी वीडियो को डिकोड किया जा सकता है.

किसी भी स्थिति में, यह उदाहरण कोड किसी भी मौजूदा कमांड लाइन यूटिलिटी को WebAssembly मॉड्यूल के तौर पर चलाने में मदद करने के लिए, गाइड के तौर पर काम का है. साथ ही, इससे यह भी पता चलता है कि आज वेब पर क्या-क्या किया जा सकता है.

क्रेडिट देखें

समीक्षा और सुझाव देने के लिए, जेफ़ पॉसनिक, एरिक बिडलमैन, और थॉमस स्टेनर का धन्यवाद.