ऑडियो वर्कलेट के बारे में पिछले लेख में, इसके बुनियादी कॉन्सेप्ट और इस्तेमाल के बारे में बताया गया है. Chrome 66 में लॉन्च होने के बाद से, इस बारे में कई अनुरोध मिले हैं कि इसे असल ऐप्लिकेशन में कैसे इस्तेमाल किया जा सकता है. ऑडियो वर्कलेट, WebAudio की पूरी क्षमता को अनलॉक करता है. हालांकि, इसका फ़ायदा लेना चुनौती भरा हो सकता है, क्योंकि इसके लिए कई JS एपीआई के साथ काम करने वाली प्रोग्रामिंग को समझना ज़रूरी है. WebAudio के बारे में जानने वाले डेवलपर के लिए भी, ऑडियो वर्कलेट को अन्य एपीआई (जैसे, WebAssembly) के साथ इंटिग्रेट करना मुश्किल हो सकता है.
इस लेख में, ऑडियो वर्कलेट को असल सेटिंग में इस्तेमाल करने का तरीका बताया गया है. साथ ही, इसकी पूरी क्षमता का इस्तेमाल करने के लिए सलाह भी दी गई है. कोड के उदाहरण और लाइव डेमो भी देखना न भूलें!
रीकैप: ऑडियो वर्कलेट
इस बारे में ज़्यादा जानने से पहले, ऑडियो वर्कलेट सिस्टम के बारे में कुछ शब्दों और तथ्यों को दोबारा याद करते हैं. इस सिस्टम के बारे में पहले इस पोस्ट में बताया गया था.
- BaseAudioContext: Web Audio API का मुख्य ऑब्जेक्ट.
- ऑडियो वर्कलेट: ऑडियो वर्कलेट ऑपरेशन के लिए, स्क्रिप्ट फ़ाइल लोड करने वाला एक खास टूल. यह BaseAudioContext से जुड़ा है. BaseAudioContext में एक ऑडियो वर्कलेट हो सकता है. लोड की गई स्क्रिप्ट फ़ाइल का आकलन, AudioWorkletGlobalScope में किया जाता है. साथ ही, इसका इस्तेमाल AudioWorkletProcessor इंस्टेंस बनाने के लिए किया जाता है.
- AudioWorkletGlobalScope : ऑडियो वर्कलेट ऑपरेशन के लिए, एक खास JS ग्लोबल स्कोप. यह WebAudio के लिए, रेंडरिंग के लिए खास तौर पर बनाई गई थ्रेड पर चलता है. BaseAudioContext में एक AudioWorkletGlobalScope हो सकता है.
- AudioWorkletNode : ऑडियो वर्कलेट ऑपरेशन के लिए डिज़ाइन किया गया AudioNode. इसे BaseAudioContext से इंस्टैंशिएट किया जाता है. नेटिव AudioNodes की तरह ही, BaseAudioContext में कई AudioWorkletNodes हो सकते हैं.
- AudioWorkletProcessor : यह AudioWorkletNode का एक हिस्सा है. उपयोगकर्ता के दिए गए कोड की मदद से, ऑडियो स्ट्रीम को प्रोसेस करने वाले AudioWorkletNode के मुख्य हिस्से की जानकारी. AudioWorkletNode बनने पर, इसे AudioWorkletGlobalScope में इंस्टैंशिएट किया जाता है. किसी AudioWorkletNode में, मैच करने वाला एक AudioWorkletProcessor हो सकता है.
डिज़ाइन पैटर्न
WebAssembly के साथ ऑडियो वर्कलेट का इस्तेमाल करना
WebAssembly, AudioWorkletProcessor के लिए सबसे सही साथी है. इन दोनों सुविधाओं के साथ काम करने पर, वेब पर ऑडियो प्रोसेस करने के कई फ़ायदे मिलते हैं. हालांकि, इनमें से दो सबसे बड़े फ़ायदे ये हैं: a) मौजूदा C/C++ ऑडियो प्रोसेसिंग कोड को WebAudio नेटवर्क में शामिल करना और b) ऑडियो प्रोसेसिंग कोड में JS JIT कंपाइलेशन और गै़रबेज कलेक्शन के ओवरहेड से बचना.
पहला अपडेट, उन डेवलपर के लिए अहम है जिन्होंने ऑडियो प्रोसेस करने वाले कोड और लाइब्रेरी में पहले से ही निवेश किया है. हालांकि, दूसरा अपडेट एपीआई के ज़्यादातर उपयोगकर्ताओं के लिए ज़रूरी है. WebAudio की दुनिया में, स्थिर ऑडियो स्ट्रीम के लिए टाइमिंग बजट काफ़ी ज़रूरी है: यह 44.1 किलोहर्ट्ज़ के सैंपल रेट पर सिर्फ़ 3 मिलीसेकंड है. ऑडियो प्रोसेस करने वाले कोड में थोड़ी सी भी गड़बड़ी होने पर, गड़बड़ियां हो सकती हैं. डेवलपर को प्रोसेसिंग तेज़ करने के लिए, कोड को ऑप्टिमाइज़ करना चाहिए. साथ ही, जनरेट होने वाले जेएस गै़रबे़ज को कम करना चाहिए. WebAssembly का इस्तेमाल करके, इन दोनों समस्याओं को एक साथ हल किया जा सकता है: यह तेज़ है और कोड से कोई गै़र-ज़रूरी डेटा जनरेट नहीं करता.
अगले सेक्शन में बताया गया है कि ऑडियो वर्कलेट के साथ WebAssembly का इस्तेमाल कैसे किया जा सकता है. साथ ही, उससे जुड़ा कोड उदाहरण यहां देखा जा सकता है. Emscripten और WebAssembly (खास तौर पर Emscripten glue कोड) का इस्तेमाल करने के बुनियादी ट्यूटोरियल के लिए, कृपया यह लेख पढ़ें.
सेटअप करना
यह सुनने में अच्छा लगता है, लेकिन चीज़ों को सही तरीके से सेट अप करने के लिए, हमें थोड़ा स्ट्रक्चर चाहिए. डिज़ाइन से जुड़ा पहला सवाल यह है कि WebAssembly मॉड्यूल को कैसे और कहां इंस्टैंशिएट किया जाए. Emscripten के ग्लू कोड को फ़ेच करने के बाद, मॉड्यूल को दो तरीकों से इंस्टैंशिएट किया जा सकता है:
audioContext.audioWorklet.addModule()
के ज़रिए, AudioWorkletGlobalScope में ग्लू कोड लोड करके, WebAssembly मॉड्यूल को इंस्टैंशिएट करें.- मुख्य स्कोप में WebAssembly मॉड्यूल को इंस्टैंशिएट करें. इसके बाद, AudioWorkletNode के कन्स्ट्रक्टर के विकल्पों के ज़रिए मॉड्यूल को ट्रांसफ़र करें.
यह फ़ैसला, आपके डिज़ाइन और प्राथमिकता पर निर्भर करता है. हालांकि, इसका मकसद यह है कि WebAssembly मॉड्यूल, AudioWorkletGlobalScope में WebAssembly इंस्टेंस जनरेट कर सकता है. यह इंस्टेंस, AudioWorkletProcessor इंस्टेंस में ऑडियो प्रोसेसिंग कर्नेल बन जाता है.
पैटर्न A के सही तरीके से काम करने के लिए, Emscripten को हमारे कॉन्फ़िगरेशन के लिए सही WebAssembly glue कोड जनरेट करने के लिए कुछ विकल्पों की ज़रूरत होती है:
-s BINARYEN_ASYNC_COMPILATION=0 -s SINGLE_FILE=1 --post-js mycode.js
इन विकल्पों से यह पक्का होता है कि AudioWorkletGlobalScope में, WebAssembly मॉड्यूल को सिंक करके कंपाइल किया जाए. यह mycode.js
में AudioWorkletProcessor की क्लास की परिभाषा भी जोड़ता है, ताकि मॉड्यूल शुरू होने के बाद इसे लोड किया जा सके.
सिंक्रोनस कंपाइलेशन का इस्तेमाल करने की मुख्य वजह यह है कि audioWorklet.addModule()
के प्रॉमिस रिज़ॉल्यूशन में, AudioWorkletGlobalScope में मौजूद प्रॉमिस रिज़ॉल्यूशन का इंतज़ार नहीं किया जाता. आम तौर पर, मुख्य थ्रेड में सिंक्रोनस लोडिंग या कंपाइलेशन का सुझाव नहीं दिया जाता, क्योंकि इससे उसी थ्रेड में मौजूद अन्य टास्क ब्लॉक हो जाते हैं. हालांकि, यहां हम इस नियम को बायपास कर सकते हैं, क्योंकि कंपाइलेशन, AudioWorkletGlobalScope पर होता है, जो मुख्य थ्रेड से अलग चलता है. ज़्यादा जानकारी के लिए, यह देखें.
पैटर्न B तब फ़ायदेमंद हो सकता है, जब एक साथ कई काम करने की ज़रूरत हो. यह सर्वर से ग्लू कोड फ़ेच करने और मॉड्यूल को कॉम्पाइल करने के लिए, मुख्य थ्रेड का इस्तेमाल करता है. इसके बाद, यह AudioWorkletNode के कन्स्ट्रक्टर के ज़रिए WASM मॉड्यूल को ट्रांसफ़र करेगा. यह पैटर्न तब ज़्यादा काम का होता है, जब आपको AudioWorkletGlobalScope के ऑडियो स्ट्रीम को रेंडर करने के बाद, मॉड्यूल को डाइनैमिक तौर पर लोड करना हो. मॉड्यूल के साइज़ के आधार पर, रेंडरिंग के बीच में इसे कंपाइल करने से स्ट्रीम में गड़बड़ियां हो सकती हैं.
WASM ढेर और ऑडियो डेटा
WebAssembly कोड सिर्फ़ खास WASM ढेर में एलोकेट की गई मेमोरी पर काम करता है. इसका फ़ायदा पाने के लिए, ऑडियो डेटा को WASM ढेर और ऑडियो डेटा ऐरे के बीच बार-बार क्लोन करना पड़ता है. उदाहरण के तौर पर दिए गए कोड में, HeapAudioBuffer क्लास इस ऑपरेशन को बेहतर तरीके से मैनेज करती है.
WASM ढेर को सीधे ऑडियो वर्कलेट सिस्टम में इंटिग्रेट करने के लिए, एक शुरुआती प्रस्ताव पर चर्चा की जा रही है. JS मेमोरी और WASM ढेर के बीच, इस ग़ैर-ज़रूरी डेटा को क्लोन करने से छुटकारा पाना स्वाभाविक लगता है. हालांकि, इस बारे में ज़्यादा जानकारी की ज़रूरत है.
बफ़र साइज़ मेल न खाने की समस्या को हल करना
AudioWorkletNode और AudioWorkletProcessor को एक साथ इस्तेमाल करने पर, यह एक सामान्य AudioNode की तरह काम करता है. AudioWorkletNode, दूसरे कोड के साथ इंटरैक्शन को मैनेज करता है, जबकि AudioWorkletProcessor, ऑडियो को प्रोसेस करने की प्रोसेस को मैनेज करता है. एक बार में 128 फ़्रेम प्रोसेस करने वाले सामान्य AudioNode की तरह, AudioWorkletProcessor को भी मुख्य सुविधा बनने के लिए ऐसा करना होगा. ऑडियो वर्कलेट के डिज़ाइन का यह एक फ़ायदा है. इससे यह पक्का होता है कि ऑडियो वर्कलेट प्रोसेसर में, इंटरनल बफ़रिंग की वजह से कोई अतिरिक्त इंतज़ार न हो. हालांकि, अगर प्रोसेसिंग फ़ंक्शन के लिए 128 फ़्रेम से अलग बफ़र साइज़ की ज़रूरत होती है, तो यह समस्या हो सकती है. इस तरह के मामले में आम तौर पर, रिंग बफ़र का इस्तेमाल किया जाता है. इसे सर्कुलर बफ़र या एफ़आईएफ़ओ भी कहा जाता है.
यहां AudioWorkletProcessor का डायग्राम दिया गया है. इसमें दो रिंग बफ़र का इस्तेमाल किया गया है, ताकि WASM फ़ंक्शन को 512 फ़्रेम इन और आउट करने में मदद मिल सके. (यहां 512 का नंबर मनमुताबिक चुना गया है.)
डायग्राम के लिए एल्गोरिदम यह होगा:
- AudioWorkletProcessor, अपने इनपुट से 128 फ़्रेम को इनपुट रिंगबफ़र में डालता है.
- यह तरीका सिर्फ़ तब अपनाएं, जब इनपुट रिंगबफ़र में 512 फ़्रेम या उससे ज़्यादा फ़्रेम हों.
- इनपुट रिंगबफ़र से 512 फ़्रेम खींचें.
- दिए गए WASM फ़ंक्शन की मदद से, 512 फ़्रेम प्रोसेस करें.
- आउटपुट रिंगबफ़र में 512 फ़्रेम डालें.
- AudioWorkletProcessor, अपने आउटपुट को भरने के लिए, आउटपुट रिंगबफ़र से 128 फ़्रेम लेता है.
डायग्राम में दिखाए गए तरीके के मुताबिक, इनपुट फ़्रेम हमेशा इनपुट रिंगबफ़र में इकट्ठा होते हैं. साथ ही, यह बफ़र में सबसे पुराने फ़्रेम ब्लॉक को ओवरराइट करके, बफ़र ओवरफ़्लो को मैनेज करता है. रीयल-टाइम ऑडियो ऐप्लिकेशन के लिए, ऐसा करना सही है. इसी तरह, सिस्टम हमेशा आउटपुट फ़्रेम ब्लॉक को खींचेगा. आउटपुट रिंगबफ़र में बफ़र अंडरफ़्लो (ज़रूरत के मुताबिक डेटा न होना) होने पर, स्क्रीन पर कुछ समय के लिए आवाज़ नहीं आएगी. इससे स्ट्रीम में रुकावट आएगी.
यह पैटर्न, ScriptProcessorNode (SPN) को AudioWorkletNode से बदलने के दौरान काम आता है. एसपीएन की मदद से, डेवलपर 256 से 16,384 फ़्रेम के बीच का बफ़र साइज़ चुन सकता है. इसलिए, एसपीएन को AudioWorkletNode के साथ ड्रॉप-इन करने में मुश्किल हो सकती है. हालांकि, रिंग बफ़र का इस्तेमाल करके, इस समस्या को हल किया जा सकता है. इस डिज़ाइन के आधार पर, ऑडियो रिकॉर्ड करने वाला ऐप्लिकेशन बनाया जा सकता है.
हालांकि, यह समझना ज़रूरी है कि यह डिज़ाइन सिर्फ़ बफ़र साइज़ के मैच न होने की समस्या को ठीक करता है. इससे, स्क्रिप्ट कोड को चलाने के लिए ज़्यादा समय नहीं मिलता. अगर कोड, रेंडर क्वन्टम के टाइमिंग बजट (44.1 केएचज़ पर ~3 मिलीसेकंड) में टास्क पूरा नहीं कर पाता है, तो इससे बाद में होने वाले कॉलबैक फ़ंक्शन के शुरू होने के समय पर असर पड़ेगा और आखिर में गड़बड़ियां हो सकती हैं.
WASM ढेर के आस-पास मेमोरी मैनेजमेंट की वजह से, इस डिज़ाइन को WebAssembly के साथ मिक्स करना मुश्किल हो सकता है. लिखने के समय, WASM ढेर में डेटा को क्लोन किया जाना चाहिए. हालांकि, मेमोरी मैनेजमेंट को थोड़ा आसान बनाने के लिए, HeapAudioBuffer क्लास का इस्तेमाल किया जा सकता है. आने वाले समय में, उपयोगकर्ता के लिए तय की गई मेमोरी का इस्तेमाल करने के आइडिया पर चर्चा की जाएगी. इससे, डेटा का क्लोन बनाने की प्रक्रिया को कम किया जा सकेगा.
RingBuffer क्लास के बारे में जानकारी यहां देखी जा सकती है.
WebAudio का बेहतरीन इस्तेमाल: ऑडियो वर्कलेट और SharedArrayBuffer
इस लेख में आखिरी डिज़ाइन पैटर्न, कई नए एपीआई को एक ही जगह पर डालना है: ऑडियो वर्कलेट, SharedArrayBuffer, Atomics और Worker. इस मुश्किल सेटअप की मदद से, C/C++ में लिखे गए मौजूदा ऑडियो सॉफ़्टवेयर को वेब ब्राउज़र में चलाया जा सकता है. इससे उपयोगकर्ता को बेहतर अनुभव मिलता है.
इस डिज़ाइन का सबसे बड़ा फ़ायदा यह है कि ऑडियो प्रोसेसिंग के लिए, DedicatedWorkerGlobalScope का इस्तेमाल किया जा सकता है. Chrome में, WorkerGlobalScope, WebAudio रेंडरिंग थ्रेड की तुलना में कम प्राथमिकता वाली थ्रेड पर चलता है. हालांकि, AudioWorkletGlobalScope की तुलना में, इसके कई फ़ायदे हैं. DedicatedWorkerGlobalScope, दायरे में उपलब्ध एपीआई के हिसाब से कम सीमित होता है. साथ ही, Emscripten से आपको बेहतर सहायता मिल सकती है, क्योंकि Worker API कुछ सालों से मौजूद है.
इस डिज़ाइन को बेहतर तरीके से काम करने के लिए, SharedArrayBuffer की अहम भूमिका होती है. Worker और AudioWorkletProcessor, दोनों में एक साथ काम करने वाली मैसेजिंग (MessagePort) की सुविधा होती है. हालांकि, रीयल-टाइम में ऑडियो प्रोसेस करने के लिए, यह सुविधा सबसे अच्छी नहीं है. इसकी वजह यह है कि इसमें बार-बार मेमोरी को ऐलोकेट किया जाता है और मैसेजिंग में देरी होती है. इसलिए, हम पहले से ही एक मेमोरी ब्लॉक को ऐलोकेट करते हैं, जिसे दोनों थ्रेड से ऐक्सेस किया जा सकता है. इससे, डेटा को तेज़ी से एक से दूसरी ओर ट्रांसफ़र किया जा सकता है.
Web Audio API के ज़्यादातर उपयोगकर्ताओं के हिसाब से, यह डिज़ाइन सही नहीं है. ऐसा इसलिए, क्योंकि यह ऑडियो वर्कलेट का इस्तेमाल, सामान्य "ऑडियो सिंक" के तौर पर करता है और सभी काम वर्कर्स में करता है. हालांकि, C/C++ प्रोजेक्ट को JavaScript में फिर से लिखने की लागत बहुत ज़्यादा हो सकती है या यह असंभव भी हो सकता है. ऐसे में, इस डिज़ाइन को ऐसे प्रोजेक्ट के लिए लागू करना सबसे असरदार तरीका हो सकता है.
शेयर किए गए स्टेटस और एटॉमिक
ऑडियो डेटा के लिए शेयर की गई मेमोरी का इस्तेमाल करते समय, दोनों पक्षों के ऐक्सेस को ध्यान से मैनेज करना चाहिए. ऐसी समस्या को हल करने के लिए, ऐटम के तौर पर ऐक्सेस की जा सकने वाली स्थितियों को शेयर करना एक तरीका है. इस काम के लिए, हम एसएबी के साथ काम करने वाले Int32Array
का फ़ायदा ले सकते हैं.
सिंक करने का तरीका: SharedArrayBuffer और Atomics
स्टेटस कलेक्शन के हर फ़ील्ड में, शेयर किए गए बफ़र के बारे में अहम जानकारी होती है. सबसे अहम फ़ील्ड, सिंक करने के लिए होता है (REQUEST_RENDER
). इसका मकसद यह है कि वर्कर, AudioWorkletProcessor के इस फ़ील्ड को अपडेट होने का इंतज़ार करता है और अपडेट होने के बाद ऑडियो को प्रोसेस करता है. SharedArrayBuffer (SAB) के साथ-साथ, Atomics API की मदद से भी यह सुविधा मिलती है.
ध्यान दें कि दो थ्रेड को सिंक करने की सुविधा का इस्तेमाल करना ज़्यादा आसान नहीं है. Worker.process()
की शुरुआत, AudioWorkletProcessor.process()
के तरीके से ट्रिगर की जाएगी. हालांकि, AudioWorkletProcessor तब तक इंतज़ार नहीं करता, जब तक Worker.process()
पूरी तरह से काम नहीं कर लेता. ऐसा डिज़ाइन के हिसाब से होता है; AudioWorkletProcessor, ऑडियो कॉलबैक से चलता है, इसलिए इसे सिंक करके ब्लॉक नहीं किया जाना चाहिए. सबसे खराब स्थिति में, ऑडियो स्ट्रीम डुप्लीकेट हो सकती है या रुक सकती है. हालांकि, रेंडरिंग की परफ़ॉर्मेंस स्थिर होने पर, यह फिर से काम करेगी.
सेट अप करना और चलाना
ऊपर दिए गए डायग्राम में दिखाया गया है कि इस डिज़ाइन में कई कॉम्पोनेंट हैं: DedicatedWorkerGlobalScope (DWGS), AudioWorkletGlobalScope (AWGS), SharedArrayBuffer, और मुख्य थ्रेड. यहां दिए गए चरणों में बताया गया है कि शुरू करने के चरण में क्या करना चाहिए.
डेटा लेयर में इवेंट बनाने की प्रोसेस
- [Main] AudioWorkletNode कंस्ट्रक्टर को कॉल किया जाता है.
- वर्कर्स बनाएं.
- इससे जुड़ा AudioWorkletProcessor बनाया जाएगा.
- [DWGS] वर्कर्स दो SharedArrayBuffer बनाता है. (एक शेयर किए गए स्टेटस के लिए और दूसरा ऑडियो डेटा के लिए)
- [DWGS] Worker, AudioWorkletNode को SharedArrayBuffer के रेफ़रंस भेजता है.
- [Main] AudioWorkletNode, SharedArrayBuffer के रेफ़रंस को AudioWorkletProcessor को भेजता है.
- [AWGS] AudioWorkletProcessor, AudioWorkletNode को सूचना देता है कि सेटअप पूरा हो गया है.
शुरू करने की प्रोसेस पूरी होने के बाद, AudioWorkletProcessor.process()
को कॉल किया जाता है. रेंडरिंग लूप के हर दोहराव में, ये काम होने चाहिए.
रेंडरिंग लूप
- [AWGS]
AudioWorkletProcessor.process(inputs, outputs)
को हर रेंडर क्वांटम के लिए कॉल किया जाता है.inputs
को Input SAB में भेज दिया जाएगा.- आउटपुट एसएबी में ऑडियो डेटा का इस्तेमाल करके,
outputs
को भरा जाएगा. - इसके हिसाब से, नए बफ़र इंडेक्स के साथ राज्यों के एसएबी को अपडेट करता है.
- अगर आउटपुट एसएबी, अंडरफ़्लो थ्रेशोल्ड के करीब पहुंच जाता है, तो ज़्यादा ऑडियो डेटा रेंडर करने के लिए, वॉकर को जगा दें.
- [DWGS] वर्कर्स,
AudioWorkletProcessor.process()
से मिलने वाले वेक अप सिग्नल का इंतज़ार करता है (स्लीप मोड में रहता है). जब यह जागता है, तो:- राज्यों के एसएबी से बफ़र इंडेक्स फ़ेच करता है.
- आउटपुट एसएबी को भरने के लिए, इनपुट एसएबी के डेटा के साथ प्रोसेस फ़ंक्शन चलाएं.
- इसके हिसाब से, बफ़र इंडेक्स के साथ राज्यों के एसएबी को अपडेट करता है.
- यह स्लीप मोड में चला जाता है और अगले सिग्नल का इंतज़ार करता है.
उदाहरण के तौर पर दिया गया कोड यहां देखा जा सकता है. हालांकि, ध्यान दें कि इस डेमो के काम करने के लिए, SharedArrayBuffer के एक्सपेरिमेंटल फ़्लैग को चालू करना ज़रूरी है. कोड को आसान बनाने के लिए, इसे सिर्फ़ JS कोड के साथ लिखा गया है. हालांकि, ज़रूरत पड़ने पर इसे WebAssembly कोड से बदला जा सकता है. ऐसे मामले को ज़्यादा ध्यान से मैनेज किया जाना चाहिए. इसके लिए, HeapAudioBuffer क्लास की मदद से, मेमोरी मैनेजमेंट को रैप करें.
नतीजा
ऑडियो वर्कलेट का मकसद, वेब ऑडियो एपीआई को सचमुच "बड़ा किया जा सकने वाला" बनाना है. ऑडियो वर्कलेट को डिज़ाइन करने में कई साल लगे. ऐसा इसलिए, ताकि ऑडियो वर्कलेट की मदद से, Web Audio API के बाकी हिस्सों को लागू किया जा सके. इस वजह से, अब हमें इसके डिज़ाइन में ज़्यादा जटिलता का सामना करना पड़ रहा है. यह एक अनचाही चुनौती हो सकती है.
अच्छी बात यह है कि इस प्रोसेस को इतना मुश्किल इसलिए बनाया गया है, ताकि डेवलपर को ज़्यादा से ज़्यादा सुविधाएं मिल सकें. AudioWorkletGlobalScope पर WebAssembly को चलाने की सुविधा से, वेब पर बेहतर परफ़ॉर्मेंस वाली ऑडियो प्रोसेसिंग की बहुत बड़ी संभावनाएं खुलती हैं. C या C++ में लिखे गए बड़े ऑडियो ऐप्लिकेशन के लिए, SharedArrayBuffers और वर्कर्स के साथ ऑडियो वर्कलेट का इस्तेमाल करना एक आकर्षक विकल्प हो सकता है.
क्रेडिट
इस लेख के ड्राफ़्ट की समीक्षा करने और अहम सुझाव देने के लिए, क्रिस विल्सन, जेसन मिलर, जोशुआ बेल, और रेमंड टोय का विशेष धन्यवाद.