लाइव अनुवाद में ज़्यादातर देरी इंतज़ार की होती है: स्ट्रीम का, अगले शब्द का, वाक्य का। एक हिस्सा जिस पर आपका नियंत्रण है, वह है लेटेंसी मोड: कम देरी, या कम बदलाव।
श्रोता लाइव अनुवाद पढ़ते समय हर पंक्ति को वक्ता के बोलने के कुछ सेकंड बाद देखता है। यह अंतर एक नहीं, कई देरियों का योग है, जो एक श्रृंखला में जुड़ती हैं, और उनमें से ज़्यादातर एक तरह का इंतज़ार ही हैं। यह जानने से कि कौन-सा इंतज़ार किस वजह से है, लेटेंसी मोड चुनना आसान हो जाता है, और डेवलपर को यह समझ आता है कि रीडर में क्या, और कब, दिखाना है।
आँकड़ों से पहले एक उपयोगी पैमाना: एक इंसानी सिमल्टेनियस दुभाषिया आम तौर पर वक्ता से दो से चार सेकंड पीछे बोलता है। दुभाषिए इस अंतर को ear-voice span कहते हैं, और जिन भाषाओं में क्रिया वाक्य के अंत में आती है, वहाँ वे क्रिया का इंतज़ार नहीं करते, बल्कि उसका अनुमान लगाते हैं, या वाक्य को ऐसे टुकड़ों में बाँटते हैं जो अपने आप में पूरे हों। एक-दो सेकंड की देरी सॉफ़्टवेयर का दोष नहीं है; एक बहुत अच्छा इंसान भी लगभग इतनी ही देर से बोलता है।
VocalStack पर हर लाइव ट्रांसक्रिप्शन इन्हीं चरणों से, इसी क्रम में गुज़रता है, और हर चरण अपने पहले वाले का इंतज़ार करता है।
मूल भाषा का टेक्स्ट पाठक तक लगभग उसी समय पहुँचता है जब उसे बोला जाता है। अनुवाद एक-दो सेकंड बाद आता है, और बोला हुआ वाक्य अपने अनुवाद के बाद आता है, इसीलिए आवाज़ वाली क्लिप हमेशा सबसे आख़िर में पहुँचती है। श्रृंखला का पहला दिखने वाला असर, हालाँकि, किसी भी आवाज़ से बहुत पहले होता है: टेक्स्ट खुद हिलने लगता है।
लाइव ट्रांसक्रिप्ट में लोग सबसे पहले यही देखते हैं कि सबसे नए शब्द हिलते हैं। कोई वाक्यांश दिखता है, बदलता है, और फिर स्थिर हो जाता है। यह ड्राफ़्ट चरण का काम है, और इसकी वजह हर स्पीच रिकग्नाइज़र पर लागू होती है।
रिकग्नाइज़र किसी शब्द को तय करने के लिए उसके बाद आने वाले शब्द को देखता है। "I scream" और "ice cream" अगला शब्द आने तक एक जैसे सुनाई देते हैं, और आख़िरी "s" इसी शब्द का हो सकता है या अगले शब्द का। जब तक किसी शब्द के दाईं ओर ऑडियो नहीं होता, उसकी स्पेलिंग एक अनुमान ही होती है, इसलिए किसी भी लाइव ट्रांसक्रिप्ट के सबसे नए शब्द हमेशा सबसे कम पक्के होते हैं। ड्राफ़्ट बस वही अनुमान है, जिसे छिपाने के बजाय जल्दी दिखा दिया जाता है।
हर ड्राफ़्ट लाइव टेल को पूरी तरह बदल देता है: पिछले कमिट के बाद सुने गए शब्द, जो अभी भी बदल रहे हैं। कमिट अंतिम होता है। वह कभी नहीं बदलता, उसमें शब्द-स्तर के समय होते हैं, और कमिट क्रम से नंबर पाते हैं, ताकि पाठक देख सके कि कोई कमिट छूटा तो नहीं।
डेवलपर के लिए रियलटाइम API का एक नियम अनिवार्य है: हर कमिट किया हुआ सेगमेंट रेंडर करें, उनके बाद नवीनतम ड्राफ़्ट, और कमिट आते ही ड्राफ़्ट साफ़ कर दें। ड्राफ़्ट को जोड़ते जाने से टेक्स्ट दोहराया जाता है और झिलमिलाता है; कमिट बस टेल को खा जाता है। WebSocket tutorial ठीक इसी पर आधारित एक रीडर बनाता है।
होस्ट के लिए, बदलता टेक्स्ट कम देरी की कीमत है। वाक्यांश पूरा होने से पहले शब्द दिखाना ही ट्रांसक्रिप्ट को लाइव महसूस कराता है। लेकिन अनुवाद यह चाल नहीं चल सकता, क्योंकि आधे वाक्यांश से एक शब्द का अनुमान लगाया जा सकता है, पर अनुवाद का नहीं।
शब्द-क्रम की वजह से अनुवाद ड्राफ़्ट की रफ़्तार से नहीं चल सकता। जर्मन में क्रिया उपवाक्य के अंत में हो सकती है, और जापानी में क्रिया सबसे अंत में आती है। सही अनुवाद के लिए किसी भी अनुवादक को पूरा उपवाक्य चाहिए। शब्द-दर-शब्द अनुवाद श्रोता को ऐसे टुकड़े देता है, जिन्हें उपवाक्य खत्म होने पर दोबारा पढ़ना पड़े। जर्मन ने सॉफ़्टवेयर के इसे आज़माने से बहुत पहले से दुभाषियों को क्रिया का इंतज़ार करवाया है।
इसलिए VocalStack सेगमेंट नहीं, वाक्यों का अनुवाद करता है। वाक्य डिफ़ॉल्ट रूप से चालू रहते हैं, और इनके चालू रहने पर सर्वर कमिट को एक वाक्य में जोड़ता है और पूरे वाक्य का अनुवाद करता है। जब तक वाक्य खुला है, उसका अनुवाद अस्थायी है; बंद होने पर अनुवाद अंतिम हो जाता है। पाठक हर वाक्य के लिए एक प्रविष्टि रखता है और अपडेट आने पर उसे बदल देता है।
आवाज़ में और भी इंतज़ार है। केवल बंद वाक्य बोला जाता है, क्योंकि जो वाक्य अभी बदल रहा है, उसे हर संशोधन पर दोबारा बनाना पड़ेगा। लंबा वाक्य टुकड़ों में बोला जाता है, ताकि बाकी टुकड़े बनते समय पहला टुकड़ा चल सके।
वाक्य बंद होने पर हर कमिट को अपना अलग अनुवाद फ़्रेम मिलता है। इस रास्ते पर कोई इंतज़ार नहीं होता, पर पूरे वाक्य कहीं ज़्यादा अच्छे पढ़े जाते हैं।
ये सारे इंतज़ार उस क्षण से मापे जाते हैं जब ऑडियो VocalStack तक पहुँचता है। कई प्रसारणों के लिए, वहाँ पहुँचने से पहले ही ऑडियो देर से था।
जब स्रोत माइक्रोफ़ोन के बजाय स्ट्रीम हो, तो कुछ भी ट्रांसक्राइब होने से पहले ही ऑडियो पीछे होता है। वह लाइव एज से पीछे रहता है, यानी स्ट्रीम द्वारा प्रकाशित सबसे नया क्षण।
सादी HTTP ऑडियो स्ट्रीम, जैसी ज़्यादातर इंटरनेट रेडियो स्टेशन प्रकाशित करते हैं, आम तौर पर एक से तीन सेकंड पीछे चलती है। सर्वर एक burst buffer रखता है: हाल के ऑडियो के कुछ सेकंड, जो एक साथ भेजे जाते हैं, ताकि नया श्रोता का प्लेयर बिना रुके शुरू हो सके। हर श्रोता, VocalStack समेत, उतना ही पीछे से जुड़ता है। HLS इससे भी बुरा है: उसकी प्लेलिस्ट क्लाइंट को लाइव एज से तीन सेगमेंट पीछे से शुरू करती है, जिसका व्यवहार में अर्थ सेगमेंट की लंबाई के आधार पर कई सेकंड से लेकर आधे मिनट तक है। Standard DASH आम तौर पर HLS जैसी ही सीमा में आता है; केवल उसका low-latency रूप इससे काफ़ी कम पर आता है। किसी स्टेशन की "लाइव" स्ट्रीम उतनी ही लाइव हो सकती है, जितनी कोई पुरानी चिट्ठी "ताज़ा" होती है।
ये आँकड़े अनुमानित हैं, और ये स्ट्रीम के हैं, ट्रांसक्रिप्शन के नहीं: VocalStack की ओर की कोई सेटिंग इन्हें वापस नहीं ला सकती। अगर किसी इवेंट के लिए ये सेकंड मायने रखते हैं, तो सार्वजनिक स्ट्रीम के बजाय माइक्रोफ़ोन या एन्कोडर से ऑडियो दें। स्ट्रीम की देरी VocalStack के एक भी शब्द सुनने से पहले तय हो चुकी होती है; जिस चीज़ को आप सचमुच बदल सकते हैं, वह लेटेंसी मोड है।
लेटेंसी मोड सिर्फ़ एक काम करता है: देरी और सटीकता के बीच संतुलन तय करता है। यह सेटिंग लाइव ट्रांसक्रिप्शन बनाते समय Advanced के नीचे मिलती है, और चलते समय Speed टैब पर। वहाँ चिप AUTO, SPEED या ACCURACY दिखाती है (Fast, SPEED के रूप में दिखता है)। API पर session.update स्ट्रीम के बीच में इसे बदल देता है।
ट्रेड-ऑफ़ वैसा ही है जैसा नाम बताते हैं। Fast टेक्स्ट को पहले बाहर निकालता है, पर उसमें ज़्यादा बदलाव होते हैं; Accuracy थोड़ी देर लेता है और कम बदलता है। बैठे हुए दर्शक, जो अनूदित सबटाइटल पढ़ रहे हैं, शायद ही एक अतिरिक्त सेकंड पर ध्यान देते हैं, पर शब्द लगातार बदलते रहें तो ज़रूर ध्यान देते हैं। इसलिए जब तक देरी वाला चार्ट सपाट रहे, Accuracy अक्सर ज़्यादा अच्छी सेटिंग होती है। Auto अपना इरादा खुलकर बताता है: जिस लाइन को उसने अंतर भरने के लिए तेज़ किया, उस पर होस्ट के ट्रांसक्रिप्ट में FAST MODE बैज होता है, जिसके साथ नोट होता है कि वहाँ सटीकता कम हो सकती है।
किसी भी मोड में, ट्रांसक्रिप्शन पहले शब्द से पहले तैयार होना चाहिए, और उसे तैयार करने की देरी ही वह एक देरी है जो श्रृंखला सिर्फ़ एक बार चुकाती है।
कुछ प्लान पर लाइव ट्रांसक्रिप्शन शुरू होने में कुछ सेकंड लगते हैं। यह प्लान पर निर्भर है: pricing page की Start-up speed पंक्ति में Pay as you go पर कोल्ड स्टार्ट 15 सेकंड तक है, और Enterprise पर हमेशा गरम।
API पर यह इंतज़ार तब दिखता है जब सेशन शुरू हो रहा हो: तब session.loading फ़्रेम आते हैं, फिर session.ready; क्लाइंट session.ready आने के बाद ही ऑडियो भेजता है। उस बीच लिंक खोलने वाला श्रोता देखता है: "लाइव। पहली लाइन एक पल में दिखती है।" एक बार ट्रांसक्रिप्शन चल पड़े, तो यह देरी पीछे छूट जाती है, और बचता है बस यह सवाल कि बाकी देरी में से आप कितनी ढो रहे हैं।
जब लाइव ट्रांसक्रिप्शन चलता है, होस्ट का Speed टैब यह दिखाता है कि यह सब मिलकर कितना होता है: वक्ता और टेक्स्ट के बीच का मौजूदा अंतर, मोड चिप के साथ, और पूरी रिकॉर्डिंग में उस अंतर का चार्ट, उसके औसत और चरम के साथ। ट्रांसक्रिप्ट में खुद, जो लाइन श्रोताओं तक देर से पहुँची, उस पर एक बैज होता है जिसमें यह संख्या होती है कि उसके बोले जाने और पहुँचने के बीच कितने सेकंड थे।
चार्ट जो नीचे और सपाट रहे, उसका मतलब है कि मोड ऑडियो के लिए सही है। चार्ट जो चढ़ता जाए, उसका मतलब है कि पाइपलाइन पीछे छूट रही है। Accuracy पर, शायद वही समय है Auto पर जाने का, जो अंतर बंद होने तक कुछ सटीकता के बदले रफ़्तार देता है।
डेवलपर को इसके बदले एक ही संख्या मिलती है। जब रियलटाइम सेशन खत्म होता है, session.done में stats.realtimeFactor होता है: ट्रांसक्राइब हुआ ऑडियो, उसे ट्रांसक्राइब करने में लगे समय से भाग दिया हुआ। एक परंपरा की चेतावनी: स्पीच-रिकग्निशन साहित्य में real-time factor आम तौर पर इसका उल्टा होता है, यानी प्रोसेसिंग समय ÷ ऑडियो समय, जहाँ कम बेहतर है। VocalStack इसे उल्टी तरफ़ से रिपोर्ट करता है, इसलिए यहाँ ज़्यादा बेहतर है: लाइव सेशन लगभग 1 के आसपास रहता है, और 1 से कम का अर्थ है कि ऑडियो उससे तेज़ आया जितनी तेज़ पाइपलाइन उसे ट्रांसक्राइब कर सकती है।
इनमें से कोई सेकंड रहस्यमय नहीं है। कुछ स्ट्रीम के हैं, कुछ एक शब्द के अगले शब्द का इंतज़ार करने के, कुछ उस वाक्य के जिसे अनुवाद चाहिए, और बाकी उस लेटेंसी मोड के जो आपने चुना। API reference में फ़्रेम-दर-फ़्रेम ब्यौरा है, और home page पर डेमो यह श्रृंखला चलते हुए दिखाता है।