- वीडियो कॉन्फ्रेंस के दौरान reMarkable 2 स्केच शेयर करने वाला टूल अब लैपटॉप की local service के बिना खुलने लगा है, जिससे presenter सिर्फ browser से तुरंत streaming शुरू कर सकता है
- नया architecture reMarkable के अंदरूनी HTTP server और browser के JavaScript client तक सरल हो गया है, जो raw image लेकर उसे
canvasपर draw करता है - WebSocket वाला विकल्प काम करता था, लेकिन iOS की समस्याएं और server overhead बचे रहे, इसलिए इसे raw stream तरीके में व्यवस्थित किया गया: fixed-resolution images को
http.ResponseWriterमें लगातार लिखना औरfetchstream से पढ़ना - 1872x1404 raw frame करीब 2.5MB का होता है, इसलिए firmware 3.3 के बाद 16 color values को uint4 में pack करके इसे 50% घटाया गया और RLE से average 200KB transfer तक कम किया गया
/dev/input/event*को monitor कर input न होने पर नए frames भेजना रोक दिया जाता है; connected clients होने पर भी CPU usage 0 तक गिर जाता है और लिखते समय करीब 10% CPU पर चलता है
पुराने टूल में असुविधा क्यों थी
- 2021 में बनाया गया reMarkable streaming tool वीडियो कॉन्फ्रेंस के दौरान sketches शेयर करने के लिए इस्तेमाल होता था, और सिर्फ browser tab शेयर करना पड़ता था, इसलिए presentation content पर focus करना आसान था
- पुराना implementation तीन components में बंटा था
- Server: reMarkable device पर चलता है और current screen की raw image expose करता है
- Client: laptop पर server की raw image लाता है और उसे browser द्वारा देखे जा सकने वाले format में process करता है
- Renderer: browser या VLC की तरह HTTP MJPEG stream पढ़कर screen पर दिखाता है
- device CPU usage घटाने के लिए server सिर्फ client connected होने पर image extract करता था, और communication के लिए gRPC इस्तेमाल होता था
- laptop client बार-बार images लाता, उन्हें JPEG में encode करता, और MJPEG stream को HTTP service के रूप में provide करता था
- presentation environment में reMarkable address, client execution permissions, और renderer को पता होना चाहिए ऐसा client IP जैसे network configuration बोझ बन जाते थे
सिर्फ browser से खुलने वाला नया architecture
- नया लक्ष्य यह था कि किसी भी browser में केवल reMarkable address डालने पर stream access हो जाए
- अलग laptop client हटाकर, reMarkable के server component के अंदर HTTP server डालने वाला structure अपनाया गया
- browser में चलने वाले client के लिए JavaScript या WASM form चाहिए था
- शुरुआत में Go experience का फायदा उठाने के लिए WASM compilation पर विचार किया गया, लेकिन काफी modifications मांगने वाली limitations के कारण उसे छोड़ दिया गया
- client का दूसरा version आखिरकार JavaScript में लिखा गया
- JavaScript code snippets और explanations पाने की प्रक्रिया में ChatGPT का इस्तेमाल किया गया, लेकिन desired solution की direction खुद तय की गई
canvas rendering तरीका
- MJPEG stream से हटने के लिए browser की image manipulation primitive
canvasका इस्तेमाल किया गया - reMarkable से मिली raw image को
Uint8Arrayके रूप में पढ़ा जाता है,ImageDataके RGBA pixel data में वही value R/G/B में डाली जाती है, और alpha value 255 set करके display किया जाता है - responsive display, rotation, और colorization की संभावना के लिए fixed size वाले
fixedCanvasको hidden state में रखा जाता है - display canvas पर
drawImageसे hidden canvas की सामग्री copy की जाती है - browser window size बदलने पर container size और 1872/1404 ratio के आधार पर display canvas की width और height adjust की जाती है
WebSocket छोड़कर raw stream पर switch
- gRPC web development में आम choice नहीं है, इसलिए पहले replacement implementation में communication और encapsulation के साधन के रूप में WebSocket का इस्तेमाल किया गया
- WebSocket messages में raw image होती है, और browser client हर message मिलने पर canvas update करता है ताकि यह streaming जैसा दिखे
- इस तरीके से server-side message भेजने की frequency control करके reMarkable की memory और CPU load manage की जा सकती थी
- लेकिन iOS पर problems थीं, और server-side WebSocket implementation का overhead भी control करना मुश्किल था
- final structure में encapsulation हटाकर fixed image size का उपयोग करते हुए raw image को सीधे network पर भेजा गया
- Go server images को बार-बार
http.ResponseWriterमेंWriteकरता है - browser client
fetch('/stream')केReadableStreamको पढ़ता है और incoming chunks को canvas data में reflect करता है
- Go server images को बार-बार
transfer size optimization
- reMarkable 2 की raw image 1872x1404 resolution पर करीब 2.5MB होती है, और यह data हर frame में transfer होना होता है
- firmware 3.3 के बाद reMarkable की 16 color values को uint8 की जगह uint4 array के रूप में represent किया जा सकता है
- Go और JavaScript में native uint4 type नहीं है
- workaround के तौर पर दो pixel values को एक uint8 byte में store किया गया
- Go में दो uint4 values को upper 4 bits और lower 4 bits में pack किया जाता है, और JavaScript में इन्हें फिर unpack किया जाता है
- यह representation data size को 50% घटा सकता है
- extra compression के लिए Run Length Encoding (RLE) इस्तेमाल किया गया
- RLE एक simple algorithm है जो एक जैसे pixel values के लगातार आने की count और value साथ में भेजता है
- example
0 0 0 0 0 0 1 1 1 0 0 0 0को6 0 3 1 4 0के रूप में represent किया जाता है
- count value अधिकतम 1872*1404 तक बढ़ सकती है, इसलिए uint64 जैसा type चाहिए हो सकता है, और कुछ मामलों में compressed result original से बड़ा होने का risk है
- इससे बचने के लिए count length को 15 तक limit किया गया और count व pixel value को एक byte में रखने वाला balance point चुना गया
- RLE implementation Go के
io.Writerजैसा काम करता है, इसलिए reusable है; जरूरत हो तो RLE दो बार भी apply किया जा सकता है, लेकिन फिलहाल इसकी जरूरत नहीं थी - packing और RLE के बाद average transfer size करीब 200KB है
बदलाव होने पर ही frame भेजना
- अंतिम optimization यह है कि नया frame सिर्फ screen बदलने पर भेजा जाए
- change detection को checksum से compute करने पर CPU load बढ़ सकता है
- reMarkable Linux-based है, इसलिए pen या touch input
/dev/input/event*के माध्यम से deliver होता है - एक goroutine इन input events को monitor करता है और केवल जरूरत पड़ने पर image भेजता है
- events न होने पर, client connected रहने पर भी CPU usage 0 तक गिर जाता है
- writing के दौरान CPU usage करीब 10% स्तर पर रहता है
firmware changes और maintenance burden
- यह application hacking पर आधारित है, और मुख्य challenge images लाने वाले interface तथा client/renderer को effectively अलग करना है
- पिछले implementation में protobuf definitions के जरिए client और server पूरी तरह अलग थे
- reMarkable 3.3 firmware ने tool को तोड़ दिया था, और संबंधित जानकारी GitHub issue 36 में है
- उस समय fix ने केवल client component को प्रभावित किया
- firmware 3.6 भी GitHub issue 58 के अनुसार breaking change ला सकता है
- इस मामले में अधिक व्यापक modifications की जरूरत हो सकती है
- हालांकि client server में integrated self-contained structure है, इसलिए device update ज्यादा simple हो सकता है
- application और source code github.com/owulveryck/goMarkableStream पर उपलब्ध हैं
1 टिप्पणियां
Hacker News की राय
2021 के उस टूल को फिर से सुधारा और जारी किया गया, जो reMarkable टैबलेट की स्क्रीन को लैपटॉप पर स्ट्रीम करता था, और नए लेख में architecture, components और user experience को बेहतर बनाने की प्रक्रिया को गहराई से कवर किया गया
Product manager के नज़रिए से देखा गया कि यूज़र कैसा महसूस करता है, activation process को सरल बनाया गया, इसे local service के बिना चलने लायक बनाया गया और network usage भी optimize किया गया
Ctrl-Cके बाद./goMarkableStreamसे restart करने पर कुछ हद तक चला, लेकिन अब भीwaiting for reMarkable screenअक्सर दिखता है और service unstable हैreMarkable2 को 3.5.2.1807 पर update करने के बाद install किया, लेकिन laptop, sheet और book पर drawing करने पर भी कोई response नहीं था, और कभी-कभी
read /dev/input/event2: file already closed,read /dev/input/event1: file already closedजैसे logs दिखेhttps://192.168.8.143:2001/ और https://10.11.99.1:2001/ दोनों HTML और canvas serve करते हैं, और Chrome, Firefox, Brave में भी कोशिश की
हर stream पर एक browser, एक IP की limit जैसी लगती है, लेकिन कोई भी address और browser इस्तेमाल करने पर भी कभी-कभी
waiting for reMarkable screenदिखता है।nohup ./goMarkableStream &के बाद PuTTY बंद करके client restart किया तो सभी browsers उसी state में आ गए, और https://10.11.99.1:2001/stream देखने परtoo many requestsreturn होता है। जानना चाहता हूँ कि stream को कैसे restart करना चाहिएविकल्प के तौर पर SuperNote को बहुत संतुष्टि के साथ इस्तेमाल कर रहा हूँ। Screen mirroring संभव है, इसलिए meetings के दौरान जल्दी diagram बनाना बहुत अच्छा रहता है
कमी यह है कि SuperNote एक छोटा web server चलाता है और Firefox से connect करने का तरीका अपनाता है, इसलिए laptop और SuperNote को same network पर होना पड़ता है। Home office में समस्या नहीं है, लेकिन company policy के कारण block हो सकता है
RM2 हो या SuperNote, pen और paper पर ideas लिखना पसंद करने वालों के लिए ये बेहतरीन tools हैं, apps या text documents से इनका feel काफी अलग है, और notes में doodle भी कर सकते हैं
[0]: https://supernote.com/
हालांकि खरीदते समय GPL violation को स्वीकार करना पड़ेगा। पूरी तरह Android-based होने के बावजूद operating system source release नहीं करता
चिंता है कि कहीं ऐसा device न खरीद बैठूँ जिसे अगले 3–5 सालों तक feature updates या कम-से-कम security updates भी न मिलें
HTML canvas rendering यहाँ बताए गए तरीके की तरह typed arrays इस्तेमाल करने पर तेज़ हो सकती है: https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipu...
ऐसी पोस्ट ही वह content है जिसे मैं यहाँ देखना चाहता हूँ। अच्छा लगा कि ChatGPT ने ऐसे domain की समस्या सीखने और हल करने में कैसे मदद की, जिसके बारे में वह ज्यादा नहीं जानता था, और “मैं developer था और ChatGPT coder था” वाली बात से सहमत हूँ
यह बात भी सही है कि simplicity असल में complex होती है
JPEG चुनने की वजह शायद यह रही होगी कि MJPEG में बदलना आसान है, और supporting side को दे दें तो decoding लगभग मुफ्त में handle हो जाती है। हालांकि यह reMarkable CPU पर बड़ा बोझ डालने वाला factor हो सकता है
JPEG photos के लिए ज्यादा suitable है, लेकिन reMarkable screen illustration जैसी है, ऊपर से black-and-white range में है। PNG जैसे दूसरे सामान्य image format या सिर्फ simple RLE compression इस्तेमाल करने पर भी CPU load कम हो सकता है
और proprietary file format bitmap नहीं, बल्कि handwriting input based है
Profiling करने पर पता चला कि CPU का ज्यादातर हिस्सा wire के जरिए data transfer में लग रहा था, इसलिए compression जोड़ा। अब CPU usage कम है
क्या आपने सिर्फ framebuffer के बदले हुए areas भेजने का तरीका consider किया है? इससे data transfer rate काफी घट सकता है: https://github.com/pl-semiotics/mxc_epdc_fb_damage
rM VNC project भी ऐसा करता है, लेकिन मुझे इस app का user experience ज्यादा पसंद है क्योंकि client-side software की जरूरत नहीं होती
वाकई शानदार है और मैं ReMarkable 2 को पसंद करना चाहता हूँ, लेकिन इसे असुरक्षित device मानने की वजह से यह आसान नहीं है: https://support.remarkable.com/s/article/Does-reMarkable-off...
यह उन known software vulnerabilities की बात नहीं है जो आमतौर पर network से जुड़े insecure device के बारे में सोचते समय दिमाग में आती हैं
“शुरुआत में client को WASM में compile करने की कोशिश की थी। Go development experience का फायदा उठा सकते थे, इसलिए यह promising लग रहा था, लेकिन कई limitations सामने आईं जिनमें काफी बदलावों की जरूरत थी” — इस हिस्से के बारे में और पढ़ना चाहूँगा
भले ही MJPEG stream बना भी लेते, उसे display कैसे करना है यह भी समस्या थी। canvas तरीका सोचा था, लेकिन WASM और JS के बीच बड़े copies किए बिना canvas backend तक पहुँचना मुश्किल था, और size भी 2.5MB था
आखिरकार लगा कि WASM पर निर्भर रहने से image rotation जैसे कई basic image operations खुद implement करने पड़ेंगे, जो JS में native रूप से accessible हैं
जानना चाहता हूँ कि यह tool built-in streaming, यानी screen sharing feature से कैसे अलग है
https://support.remarkable.com/s/article/Screen-Share
लेख का solution सिर्फ एक सक्षम browser होने पर Linux पर भी काम करता दिखता है
मुझे reMarkable पसंद है, लेकिन काश वे उस subscription के बजाय, जिसके लिए मैं आगे भी पैसे देने का इरादा नहीं रखता, ऐसी streaming features पर ध्यान दें