3 คะแนน โดย GN⁺ 2023-08-21 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เครื่องมือที่ใช้แชร์สเก็ตช์จาก reMarkable 2 ระหว่างการประชุมวิดีโอถูกปรับให้เปิดใช้งานได้โดยไม่ต้องพึ่งบริการโลคัลบนโน้ตบุ๊ก ทำให้ผู้นำเสนอเริ่ม สตรีมแบบทันที ได้ด้วยเบราว์เซอร์อย่างเดียว
  • สถาปัตยกรรมใหม่ถูกทำให้ง่ายขึ้นเป็นรูปแบบที่ HTTP server ภายใน reMarkable และ JavaScript client ของเบราว์เซอร์รับภาพดิบแล้ววาดลงบน canvas
  • ทางเลือกอย่าง WebSocket ใช้งานได้ แต่ยังมีปัญหาบน iOS และมีโอเวอร์เฮดฝั่งเซิร์ฟเวอร์ จึงสรุปมาเป็นแนวทาง raw stream ที่เขียนภาพความละเอียดคงที่ลง http.ResponseWriter ต่อเนื่องและอ่านด้วย fetch stream
  • เฟรมดิบขนาด 1872x1404 มีขนาดราว 2.5MB ดังนั้นหลังเฟิร์มแวร์ 3.3 จึงแพ็กค่าสี 16 ระดับเป็น uint4 เพื่อลดลง 50% และใช้ RLE จนลดปริมาณการส่งข้อมูลเฉลี่ยเหลือราว 200KB
  • ด้วยการเฝ้าดู /dev/input/event* จะหยุดส่งเฟรมใหม่เมื่อไม่มีอินพุต และแม้มีไคลเอนต์เชื่อมต่ออยู่ การใช้ CPU ก็ลดลงเป็น 0 ขณะไม่ได้เขียน และทำงานที่ราว 10% CPU ระหว่างการเขียน

เหตุผลที่เครื่องมือเดิมใช้งานไม่สะดวก

  • เครื่องมือสตรีม reMarkable ที่สร้างในปี 2021 ถูกใช้เพื่อแชร์สเก็ตช์ระหว่างการประชุมวิดีโอ และเพียงแชร์แท็บเบราว์เซอร์ก็พอ จึงโฟกัสกับการนำเสนอได้ง่าย
  • การทำงานเดิมแบ่งเป็น 3 องค์ประกอบ
    • เซิร์ฟเวอร์: รันบนอุปกรณ์ reMarkable และเปิดให้เข้าถึงภาพดิบของหน้าจอปัจจุบัน
    • ไคลเอนต์: ดึงภาพดิบจากเซิร์ฟเวอร์บนโน้ตบุ๊กและประมวลผลให้อยู่ในรูปแบบที่เบราว์เซอร์ดูได้
    • เรนเดอเรอร์: อ่าน HTTP MJPEG stream แล้วแสดงผลบนหน้าจอ เช่น เบราว์เซอร์หรือ VLC
  • เพื่อลดการใช้ CPU ของอุปกรณ์ ฝั่งเซิร์ฟเวอร์จะดึงภาพเฉพาะเมื่อมีไคลเอนต์เชื่อมต่อ และใช้ gRPC ในการสื่อสาร
  • ไคลเอนต์บนโน้ตบุ๊กจะดึงภาพซ้ำ ๆ เข้ารหัสเป็น JPEG แล้วเปิดให้บริการ MJPEG stream ผ่าน HTTP
  • ในสภาพแวดล้อมการนำเสนอ การตั้งค่าเครือข่ายอย่างที่อยู่ของ reMarkable สิทธิ์ในการรันไคลเอนต์ และ IP ของไคลเอนต์ที่เรนเดอเรอร์ต้องรู้ กลายเป็นภาระ

สถาปัตยกรรมใหม่ที่เปิดได้ด้วยเบราว์เซอร์อย่างเดียว

  • เป้าหมายใหม่คือทำให้เข้าถึงสตรีมได้จากทุกเบราว์เซอร์เพียงแค่ใส่ที่อยู่ของ reMarkable
  • จึงตัดไคลเอนต์แยกบนโน้ตบุ๊กออก และเปลี่ยนเป็นโครงสร้างที่ใส่ HTTP server ไว้ในคอมโพเนนต์เซิร์ฟเวอร์ของ reMarkable
  • ไคลเอนต์ที่รันบนเบราว์เซอร์จึงต้องอยู่ในรูปแบบ JavaScript หรือ WASM
    • ตอนแรกพิจารณาคอมไพล์เป็น WASM เพื่อใช้ประสบการณ์กับ Go แต่ก็ล้มเลิกเพราะข้อจำกัดที่ต้องแก้ไขจำนวนมาก
    • สุดท้ายไคลเอนต์เวอร์ชันที่สองจึงเขียนด้วย JavaScript
  • มีการใช้ ChatGPT ระหว่างการหาโค้ด JavaScript บางส่วนและคำอธิบาย แต่ทิศทางของวิธีแก้ปัญหาที่ต้องการเป็นผู้กำหนดเอง

วิธีเรนเดอร์ด้วย canvas

  • เพื่อออกจาก MJPEG stream จึงใช้ canvas ซึ่งเป็นองค์ประกอบพื้นฐานของการจัดการภาพในเบราว์เซอร์
  • ภาพดิบที่รับมาจาก reMarkable จะถูกอ่านเป็น Uint8Array แล้วใส่ค่าเดียวกันลงในข้อมูลพิกเซล RGBA ของ ImageData สำหรับ R/G/B และตั้งค่า alpha เป็น 255 เพื่อแสดงผล
  • เพื่อรองรับการแสดงผลแบบ responsive การหมุน และความเป็นไปได้ในการใส่สี จึงคง fixedCanvas ขนาดคงที่ไว้ในสถานะซ่อน
  • สำหรับ canvas ที่ใช้แสดงผล จะคัดลอกเนื้อหาจาก canvas ที่ซ่อนไว้ด้วย drawImage
  • เมื่อขนาดหน้าต่างเบราว์เซอร์เปลี่ยน จะปรับความกว้างและความสูงของ canvas สำหรับแสดงผลตามขนาดคอนเทนเนอร์และอัตราส่วน 1872/1404

เลิกใช้ WebSocket แล้วเปลี่ยนเป็น raw stream

  • เนื่องจาก gRPC ไม่ใช่ตัวเลือกที่พบได้ทั่วไปในการพัฒนาเว็บ การแทนที่ครั้งแรกจึงใช้ WebSocket เป็นทั้งช่องทางสื่อสารและวิธีห่อข้อมูล
  • ข้อความของ WebSocket จะบรรจุภาพดิบ และไคลเอนต์บนเบราว์เซอร์จะอัปเดต canvas ทุกครั้งที่ได้รับข้อความ ทำให้ดูเหมือนการสตรีม
  • วิธีนี้ช่วยให้ควบคุมภาระหน่วยความจำและ CPU ของ reMarkable ได้ด้วยการปรับความถี่การส่งข้อความจากฝั่งเซิร์ฟเวอร์
  • แต่มีปัญหาบน iOS และยังควบคุมโอเวอร์เฮดของการใช้งาน WebSocket ฝั่งเซิร์ฟเวอร์ได้ยาก
  • โครงสร้างสุดท้ายจึงตัดการห่อข้อมูลออก และใช้ขนาดภาพคงที่เพื่อส่ง ภาพดิบ ผ่านเครือข่ายโดยตรง
    • เซิร์ฟเวอร์ Go จะ Write ภาพซ้ำ ๆ ลงใน http.ResponseWriter
    • ไคลเอนต์บนเบราว์เซอร์จะอ่าน ReadableStream จาก fetch('/stream') แล้วสะท้อน chunk ที่เข้ามาลงในข้อมูลของ canvas

ปรับปริมาณการส่งข้อมูลให้เหมาะสม

  • ภาพดิบของ reMarkable 2 มีขนาดประมาณ 2.5MB ที่ความละเอียด 1872x1404 และต้องส่งข้อมูลนี้ในทุกเฟรม
  • หลังเฟิร์มแวร์ 3.3 ค่า 16 สีของ reMarkable สามารถแสดงเป็น อาร์เรย์ uint4 แทน uint8 ได้
    • Go และ JavaScript ไม่มีชนิด uint4 แบบเนทีฟ
    • จึงแก้ด้วยการเก็บค่าพิกเซล 2 ค่าไว้ในไบต์ uint8 เดียว
    • ใน Go จะแพ็ก uint4 สองค่าไว้ใน 4 บิตบนและ 4 บิตล่าง ส่วนใน JavaScript จะคลายแพ็กกลับออกมา
    • รูปแบบนี้ช่วยลดปริมาณข้อมูลได้ 50%
  • สำหรับการบีบอัดเพิ่มเติม ใช้ Run Length Encoding (RLE)
    • RLE เป็นอัลกอริทึมง่าย ๆ ที่ส่งจำนวนครั้งและค่าของพิกเซลที่ซ้ำต่อเนื่องกันไปพร้อมกัน
    • ตัวอย่าง 0 0 0 0 0 0 1 1 1 0 0 0 0 สามารถแทนเป็น 6 0 3 1 4 0
  • ค่านับสามารถโตได้ถึง 1872*1404 จึงอาจต้องใช้ชนิดอย่าง uint64 และในบางกรณีผลบีบอัดอาจใหญ่กว่าต้นฉบับ
  • เพื่อหลีกเลี่ยงปัญหานี้ จึงจำกัดความยาวของค่านับไว้ที่ 15 และเลือกจุดสมดุลด้วยการเก็บค่านับและค่าพิกเซลไว้ในหนึ่งไบต์
  • การทำ RLE ถูกออกแบบให้ทำงานเหมือน io.Writer ของ Go จึงนำกลับมาใช้ซ้ำได้ และหากจำเป็นก็สามารถใช้ RLE ซ้ำสองรอบได้ แต่ตอนนี้ยังไม่จำเป็น
  • หลังจากแพ็กและทำ RLE แล้ว ปริมาณการส่งข้อมูลเฉลี่ยอยู่ที่ราว 200KB

ส่งเฟรมเฉพาะเมื่อมีการเปลี่ยนแปลง

  • การปรับแต่งขั้นสุดท้ายคือส่งเฟรมใหม่เฉพาะเมื่อหน้าจอมีการเปลี่ยนแปลง
  • หากตรวจการเปลี่ยนแปลงด้วย checksum อาจเพิ่มภาระ CPU มากเกินไป
  • reMarkable ใช้ Linux เป็นฐาน ดังนั้นอินพุตจากปากกาหรือการสัมผัสจะถูกส่งผ่าน /dev/input/event*
  • goroutine จะเฝ้าดู event อินพุตเหล่านี้ และส่งภาพเฉพาะเมื่อจำเป็น
  • หากไม่มี event แม้จะมีไคลเอนต์เชื่อมต่ออยู่ การใช้ CPU ก็ลดลงเป็น 0
  • ระหว่างการเขียน การใช้ CPU อยู่ที่ประมาณ 10%

การเปลี่ยนแปลงเฟิร์มแวร์และภาระในการดูแลรักษา

  • แอปพลิเคชันนี้อาศัยการแฮ็กเป็นพื้นฐาน และโจทย์สำคัญคือการแยกอินเทอร์เฟซที่ใช้ดึงภาพออกจากไคลเอนต์/เรนเดอเรอร์อย่างมีประสิทธิภาพ
  • การทำงานเดิมแยกไคลเอนต์และเซิร์ฟเวอร์ออกจากกันอย่างสมบูรณ์ผ่าน protobuf definition
  • เฟิร์มแวร์ reMarkable 3.3 ทำให้เครื่องมือใช้งานไม่ได้ โดยมีรายละเอียดใน GitHub issue 36
    • การแก้ไขในตอนนั้นกระทบเฉพาะคอมโพเนนต์ไคลเอนต์
  • เฟิร์มแวร์ 3.6 ก็อาจนำการเปลี่ยนแปลงที่ทำให้ใช้งานไม่ได้เช่นกัน ตาม GitHub issue 58
    • ในกรณีนี้อาจต้องแก้ไขในวงกว้างกว่าเดิม
    • แต่เนื่องจากไคลเอนต์ถูกรวมเข้าไว้ในเซิร์ฟเวอร์เป็นโครงสร้างแบบรวมทุกอย่างในตัว การอัปเดตอุปกรณ์อาจง่ายขึ้น
  • แอปพลิเคชันและซอร์สโค้ดมีให้ที่ github.com/owulveryck/goMarkableStream

1 ความคิดเห็น

 
GN⁺ 2023-08-21
ความคิดเห็นบน Hacker News
  • มีการนำเครื่องมือจากปี 2021 ที่ใช้สตรีมหน้าจอแท็บเล็ต reMarkable ไปยังแล็ปท็อปมาปรับปรุงและเผยแพร่อีกครั้ง โดยบทความใหม่นี้เจาะลึก สถาปัตยกรรม, องค์ประกอบต่าง ๆ และกระบวนการปรับปรุงประสบการณ์ผู้ใช้
    จากมุมมองผู้จัดการผลิตภัณฑ์ ผู้เขียนดูว่าผู้ใช้จะรู้สึกอย่างไร แล้วทำให้ขั้นตอนการเปิดใช้งานง่ายขึ้น ทำให้ทำงานได้โดยไม่ต้องมีบริการภายในเครื่อง และยังปรับการใช้งานเครือข่ายให้เหมาะสมด้วย

    • ดูเป็นโปรเจกต์ที่น่าสนใจ หลังจาก Ctrl-C แล้วเริ่มใหม่ด้วย ./goMarkableStream ก็ทำงานได้ในระดับหนึ่ง แต่ยังขึ้น waiting for reMarkable screen บ่อย และบริการยังไม่เสถียร
      ผมติดตั้งหลังอัปเดต reMarkable2 เป็น 3.5.2.1807 แต่ไม่ว่าจะวาดบนแล็ปท็อป แผ่นงาน หรือหนังสือก็ไม่ตอบสนอง และบางครั้งเห็นล็อกอย่าง read /dev/input/event2: file already closed, read /dev/input/event1: file already closed
      ทั้ง https://192.168.8.143:2001/ และ https://10.11.99.1:2001/ ต่างก็ส่ง HTML กับแคนวาสมาให้ และลองทั้ง Chrome, Firefox, Brave แล้ว
      ดูเหมือนจะจำกัดเบราว์เซอร์หนึ่งตัวและ IP หนึ่งรายการต่อสตรีม แต่ไม่ว่าจะใช้ที่อยู่หรือเบราว์เซอร์ไหน บางครั้งก็ขึ้น waiting for reMarkable screen หลังจาก nohup ./goMarkableStream & แล้วปิด PuTTY จากนั้นรีสตาร์ตไคลเอนต์ เบราว์เซอร์ทั้งหมดก็กลายเป็นสถานะเดียวกัน และเมื่อดู https://10.11.99.1:2001/stream จะได้ too many requests กลับมา อยากรู้ว่าควรรีสตาร์ตสตรีมอย่างไร
    • สงสัยว่าจะทำให้ใช้ผ่าน การเชื่อมต่อ USB ได้ด้วยหรือไม่
  • ในฐานะทางเลือก ผมใช้ SuperNote แล้วพอใจมาก มันทำ screen mirroring ได้ จึงเหมาะมากสำหรับวาดไดอะแกรมอย่างรวดเร็วระหว่างประชุม
    ข้อเสียคือ SuperNote เปิดเว็บเซิร์ฟเวอร์ขนาดเล็ก แล้วให้เชื่อมต่อด้วย Firefox ดังนั้นแล็ปท็อปกับ SuperNote ต้องอยู่ในเครือข่ายเดียวกัน ที่โฮมออฟฟิศไม่มีปัญหา แต่ในบริษัทอาจถูกนโยบายบล็อกได้
    ไม่ว่าจะเป็น RM2 หรือ SuperNote ก็เป็นเครื่องมือที่ยอดเยี่ยมสำหรับคนที่ชอบเขียนไอเดียด้วยปากกาและกระดาษ ความรู้สึกต่างจากแอปหรือเอกสารข้อความพอสมควร และยังขีดเขียนเล่นในโน้ตได้ด้วย
    [0]: https://supernote.com/

    • Onyx Boox Note ก็ทำงานได้ดี และยังออกอัปเดตแม้ผ่านไปกว่า 5 ปีแล้ว
      แต่ตอนซื้อก็ต้องยอมรับความเสี่ยงเรื่องการละเมิด GPL แม้จะใช้ Android เป็นฐานทั้งหมด แต่ก็ไม่เปิดซอร์สของระบบปฏิบัติการ
    • ผมกำลังหา แท็บเล็ตหมึกอิเล็กทรอนิกส์ สำหรับอ่านอีบุ๊กและจดโน้ต คำแนะนำนี้ช่วยได้มาก กำลังลังเลระหว่าง Remarkable 2 กับ Boox และอยากรู้ว่าประสบการณ์ด้านการอัปเดตซอฟต์แวร์ของ SuperNote เป็นอย่างไร
      กังวลว่าจะซื้ออุปกรณ์ที่ไม่ได้รับการอัปเดตฟีเจอร์ หรืออย่างน้อยอัปเดตความปลอดภัย ในช่วง 3–5 ปีข้างหน้า
    • เท่าที่จำได้ SuperNote ไม่ได้ปฏิบัติตาม GPL ของซอฟต์แวร์ที่แจกมาด้วยกัน อยากรู้ว่าท่าทีเปลี่ยนไปแล้วหรือยัง
    • ยังไม่เคยเจอปัญหา “ต้องอยู่ในเครือข่ายเดียวกัน” แต่การใส่ ฟังก์ชัน Ngrok แบบเนทีฟดูเป็นงานง่าย ๆ ที่ใช้เวลาไม่กี่นาที แบบนั้นก็จะสตรีมผ่านอินเทอร์เน็ตได้
    • อยากรู้ว่าความรู้สึกในการเขียนของ SuperNote เมื่อเทียบกับ RM2 เป็นอย่างไร
  • การเรนเดอร์ HTML canvas อาจเร็วขึ้นได้ถ้าใช้ typed arrays ตามที่อธิบายไว้ที่นี่: https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipu...

    • ขอบคุณ จะลองดู
  • บทความแบบนี้แหละคือคอนเทนต์ที่อยากเห็นที่นี่ ชอบที่เล่าว่า ChatGPT ช่วยเรียนรู้และแก้ปัญหาในพื้นที่ที่มันไม่ค่อยรู้ได้อย่างไร และเห็นด้วยกับประโยคที่ว่า “ผมเป็นนักพัฒนา และ ChatGPT เป็นโค้ดเดอร์
    คำกล่าวที่ว่าความเรียบง่ายจริง ๆ แล้วซับซ้อนก็ถูกต้อง

  • ที่เลือก JPEG น่าจะเพราะเปลี่ยนเป็น MJPEG ได้ง่าย และถ้าส่งต่อให้ฝั่งที่รองรับ ก็เหมือนได้ถอดรหัสฟรี ๆ แต่สิ่งนั้นอาจเป็นปัจจัยที่สร้างภาระหนักให้กับ CPU ของ reMarkable
    JPEG เหมาะกับภาพถ่ายมากกว่า แต่หน้าจอ reMarkable ใกล้เคียงภาพประกอบ และยิ่งไปกว่านั้นเป็นโทนขาวดำ การใช้รูปแบบภาพทั่วไปอื่น ๆ อย่าง PNG หรือแม้แต่ การบีบอัด RLE แบบง่าย ๆ ก็น่าจะทำให้ภาระ CPU ต่ำกว่า

    • พูดให้เคร่งครัด reMarkable ไม่ใช่ขาวดำล้วน แต่เป็น เฉดเทา และเท่าที่จำได้รองรับสีเทา 16 ระดับ ในแอปร่วม ยังมีหมึกสีที่แสดงเป็นปากกาสีน้ำเงิน/แดง และปากกาไฮไลต์สีเหลือง/เขียวด้วย
      และรูปแบบไฟล์ของตัวเองไม่ใช่บิตแมป แต่เป็นแบบอิงข้อมูลการเขียนด้วยปากกา
    • เหตุผลที่เลือก JPEG ตอนแรกถูกต้องแล้ว แต่เพราะแบบนั้นจึงเลือก โครงสร้างไคลเอนต์/เซิร์ฟเวอร์ และให้การเข้ารหัสทำบนแล็ปท็อปซึ่งเป็นไคลเอนต์ ไม่ใช่บนแท็บเล็ต
      เมื่อลองทำ profiling พบว่า CPU ส่วนใหญ่ถูกใช้ไปกับการส่งข้อมูลผ่านสาย จึงใส่การบีบอัดเข้ามา ตอนนี้การใช้ CPU ต่ำแล้ว
  • สงสัยว่าได้พิจารณาวิธีส่งเฉพาะ พื้นที่ของ framebuffer ที่มีการเปลี่ยนแปลง หรือยัง แบบนั้นจะลดอัตราการส่งข้อมูลได้มาก: https://github.com/pl-semiotics/mxc_epdc_fb_damage
    โปรเจกต์ rM VNC ก็ทำแบบนั้น แต่ผมชอบประสบการณ์ผู้ใช้ของแอปนี้มากกว่า เพราะไม่ต้องมีซอฟต์แวร์ฝั่งไคลเอนต์

    • ปัญหาของวิธีนั้นคือจำเป็นต้องมีการวิเคราะห์บนอุปกรณ์ในระดับหนึ่ง และอยากให้โค้ด รุกล้ำน้อยที่สุด เท่าที่ทำได้ จะลองดูว่ามีวิธีทำแบบต้นทุนต่ำหรือไม่
  • เจ๋งมาก และก็อยากจะชอบ ReMarkable 2 จริง ๆ แต่ด้วยจุดยืนที่ว่าเป็น อุปกรณ์ที่ไม่ปลอดภัย เลยไม่ง่ายนัก: https://support.remarkable.com/s/article/Does-reMarkable-off...

    • เนื้อหาในลิงก์หมายความว่าอุปกรณ์นี้มีความปลอดภัยทางกายภาพในระดับเดียวกับกระดาษที่มันตั้งใจจะมาแทนเท่านั้น กล่าวคือถ้ามีใครเข้าถึงตัวเครื่องได้ ก็อ่านได้
      ไม่ได้หมายถึงช่องโหว่ซอฟต์แวร์ที่รู้จักกันแล้ว ซึ่งมักนึกถึงกันเวลาพูดว่าเป็นอุปกรณ์ไม่ปลอดภัยที่เชื่อมต่อเครือข่าย
    • แบบไม่เป็นทางการ สามารถทำ การเข้ารหัสโฮมไดเรกทอรีที่ใช้ gocryptfs ได้: https://github.com/RedTeamPentesting/remarkable-encryption
    • ซอฟต์แวร์เองตอนนี้ก็ยังจำกัดมาก น่าเสียดายที่ยังไม่เปิดให้ใช้ marketplace หรือส่วนขยายบนอุปกรณ์อย่างเป็นทางการ
    • มี e-book reader ตัวไหนที่ให้การเข้ารหัสทั้งดิสก์บ้างไหม?
  • อยากอ่านรายละเอียดเพิ่มเติมในส่วนที่ว่า “ตอนแรกตั้งใจจะคอมไพล์ไคลเอนต์เป็น WASM ดูมีอนาคตเพราะสามารถใช้ประสบการณ์พัฒนา Go ได้ แต่ก็เจอข้อจำกัดหลายอย่างที่ต้องแก้ไขค่อนข้างมาก”

    • ปัญหาหลักคือ ไลบรารี gRPC และตอนนี้การรองรับยังจำกัดมาก อีกทั้งการบีบอัด JPEG ใน Go ก็ช้าและใช้ CPU มาก
      ต่อให้สร้างสตรีม MJPEG ได้ ก็ยังมีปัญหาว่าจะแสดงผลอย่างไร ตอนแรกคิดถึงวิธีใช้ canvas แต่เข้าถึง canvas backend ได้ยากโดยไม่ต้องคัดลอกข้อมูลขนาดใหญ่ระหว่าง WASM กับ JS และขนาดก็ 2.5MB
      สุดท้ายถ้าพึ่งพา WASM ก็ดูเหมือนจะต้อง implement การดำเนินการพื้นฐานเกี่ยวกับรูปภาพจำนวนมากเอง เช่น การหมุนภาพ ทั้งที่ JS เข้าถึงได้โดยตรงอยู่แล้ว
  • สงสัยว่าเครื่องมือนี้ต่างจากสตรีมมิงในตัว หรือก็คือ ฟีเจอร์แชร์หน้าจอ อย่างไร

    • ถ้าจะใช้ฟีเจอร์ในตัว ต้องติดตั้งแอปเดสก์ท็อป และเท่าที่รู้ไม่มีเวอร์ชัน Linux
      https://support.remarkable.com/s/article/Screen-Share
      โซลูชันในบทความดูเหมือนจะทำงานบน Linux ได้ด้วย ขอแค่มีเบราว์เซอร์ที่มีความสามารถเพียงพอ
    • ความแตกต่างใหญ่ที่สุดคือ ตอนนี้ ไม่ต้องติดตั้งไคลเอนต์ แล้ว แค่ใส่ที่อยู่ reMarkable ในเบราว์เซอร์ก็เห็นเนื้อหาได้
    • คิดว่าฟีเจอร์นี้ทำได้อยู่แล้วเสียอีก การแชร์หน้าจอก็ดีพอสมควร และใช้กับไลฟ์สตรีมมิงอยู่ด้วย
  • ชอบ reMarkable นะ แต่หวังว่าจะไปโฟกัสกับ ฟีเจอร์สตรีมมิง แบบนี้ มากกว่าสมาชิก subscription ที่ต่อไปก็ไม่คิดจะจ่ายอยู่ดี