3 poin oleh GN⁺ 2023-08-21 | 1 komentar | Bagikan ke WhatsApp
  • Alat untuk membagikan sketsa reMarkable 2 saat konferensi video diubah agar bisa dibuka tanpa layanan lokal di laptop, sehingga presenter dapat memulai streaming seketika hanya dengan browser
  • Arsitektur baru disederhanakan menjadi server HTTP di dalam reMarkable dan klien JavaScript di browser yang menerima gambar mentah lalu menggambarnya ke canvas
  • Alternatif WebSocket sempat berfungsi, tetapi masalah di iOS dan overhead server masih tersisa, sehingga akhirnya dirapikan menjadi pendekatan stream mentah: terus menulis gambar beresolusi tetap ke http.ResponseWriter dan membacanya lewat stream fetch
  • Frame mentah 1872x1404 berukuran sekitar 2.5MB, jadi setelah firmware 3.3 nilai 16 warna dipaketkan sebagai uint4 untuk mengurangi 50%, lalu dengan RLE rata-rata turun hingga sekitar 200KB per transfer
  • Dengan memantau /dev/input/event*, pengiriman frame baru dihentikan saat tidak ada input; bahkan jika klien tetap terhubung penggunaan CPU turun ke 0, dan saat menulis berjalan di sekitar 10% CPU

Mengapa alat lama terasa merepotkan

  • Alat streaming reMarkable yang dibuat pada 2021 digunakan untuk membagikan sketsa saat konferensi video, dan karena cukup membagikan tab browser, presenter jadi lebih mudah fokus pada materi presentasi
  • Implementasi lama dibagi menjadi tiga komponen
    • Server: berjalan di perangkat reMarkable dan mengekspos gambar mentah dari layar saat ini
    • Klien: mengambil gambar mentah dari server di laptop dan memprosesnya menjadi format yang bisa dilihat browser
    • Renderer: menampilkan layar dengan membaca stream HTTP MJPEG, misalnya di browser atau VLC
  • Untuk mengurangi penggunaan CPU perangkat, server hanya mengekstrak gambar saat klien terhubung, dan komunikasi menggunakan gRPC
  • Klien di laptop berulang kali mengambil gambar, mengenkodenya menjadi JPEG, lalu menyediakan stream MJPEG sebagai layanan HTTP
  • Dalam lingkungan presentasi, konfigurasi jaringan seperti alamat reMarkable, izin menjalankan klien, dan IP klien yang harus diketahui renderer menjadi beban tersendiri

Arsitektur baru yang bisa dibuka hanya dengan browser

  • Tujuan baru adalah membuat stream dapat diakses dari browser mana pun hanya dengan memasukkan alamat reMarkable
  • Klien laptop terpisah dihilangkan, dan strukturnya diubah dengan menanamkan server HTTP ke dalam komponen server di reMarkable
  • Klien yang berjalan di browser perlu berbentuk JavaScript atau WASM
    • Awalnya kompilasi ke WASM dipertimbangkan agar bisa memanfaatkan pengalaman dengan Go, tetapi dibatalkan karena keterbatasan yang membutuhkan cukup banyak perubahan
    • Klien versi kedua akhirnya ditulis dalam JavaScript
  • ChatGPT digunakan dalam proses mendapatkan potongan kode JavaScript dan penjelasannya, tetapi arah solusi yang diinginkan ditentukan sendiri

Metode rendering canvas

  • Untuk keluar dari stream MJPEG, digunakan canvas, elemen dasar manipulasi gambar di browser
  • Gambar mentah dari reMarkable dibaca sebagai Uint8Array, lalu nilai yang sama dimasukkan ke data piksel RGBA milik ImageData pada R/G/B dan nilai alfa diset ke 255 untuk ditampilkan
  • Untuk kemungkinan tampilan responsif, rotasi, dan pewarnaan, fixedCanvas berukuran tetap dipertahankan dalam keadaan tersembunyi
  • Isi kanvas tersembunyi kemudian disalin ke kanvas tampilan dengan drawImage
  • Saat ukuran jendela browser berubah, lebar dan tinggi kanvas tampilan disesuaikan berdasarkan ukuran container dan rasio 1872/1404

Meninggalkan WebSocket dan beralih ke stream mentah

  • Karena gRPC bukan pilihan yang umum dalam pengembangan web, implementasi pengganti pertama memakai WebSocket sebagai sarana komunikasi dan enkapsulasi
  • Pesan WebSocket memuat gambar mentah, dan klien browser memperbarui kanvas setiap kali pesan diterima agar terlihat seperti streaming
  • Pendekatan ini memungkinkan frekuensi pengiriman pesan di sisi server diatur untuk mengelola beban memori dan CPU pada reMarkable
  • Namun, ada masalah di iOS dan overhead implementasi WebSocket di sisi server juga sulit dikendalikan
  • Arsitektur akhirnya menghapus enkapsulasi dan memanfaatkan ukuran gambar yang tetap untuk langsung mengirim gambar mentah melalui jaringan
    • Server Go berulang kali Write gambar ke http.ResponseWriter
    • Klien browser membaca ReadableStream dari fetch('/stream') dan menerapkan chunk yang masuk ke data kanvas

Optimasi ukuran transfer

  • Gambar mentah reMarkable 2 berukuran sekitar 2.5MB pada resolusi 1872x1404, dan data ini harus ditransfer di setiap frame
  • Sejak firmware 3.3, 16 nilai warna pada reMarkable bisa direpresentasikan sebagai array uint4 alih-alih uint8
    • Go dan JavaScript tidak memiliki tipe uint4 bawaan
    • Ini diakali dengan menyimpan dua nilai piksel dalam satu byte uint8
    • Di Go, dua nilai uint4 dipaketkan ke 4 bit atas dan 4 bit bawah, lalu di JavaScript dibuka kembali
    • Representasi ini dapat mengurangi ukuran data sebesar 50%
  • Untuk kompresi tambahan digunakan Run Length Encoding (RLE)
    • RLE adalah algoritme sederhana yang mengirim jumlah kemunculan berurutan dari nilai piksel yang sama beserta nilainya
    • Contoh 0 0 0 0 0 0 1 1 1 0 0 0 0 direpresentasikan sebagai 6 0 3 1 4 0
  • Nilai hitung bisa membesar hingga 1872*1404 sehingga mungkin membutuhkan tipe seperti uint64, dan dalam beberapa kasus hasil kompresi berisiko lebih besar daripada data asli
  • Untuk menghindarinya, panjang hitungan dibatasi hingga 15, dan dipilih titik keseimbangan dengan menaruh nilai hitung dan nilai piksel dalam satu byte
  • Implementasi RLE bekerja seperti io.Writer di Go sehingga bisa digunakan kembali, dan jika perlu RLE bahkan bisa diterapkan dua kali, meski saat ini tidak diperlukan
  • Setelah packing dan RLE, rata-rata ukuran transfer berada di sekitar 200KB

Mengirim frame hanya saat ada perubahan

  • Optimasi terakhir adalah mengirim frame baru hanya saat layar berubah
  • Menghitung checksum untuk memeriksa perubahan bisa menambah beban CPU
  • reMarkable berbasis Linux, jadi input pena atau sentuhan dikirim melalui /dev/input/event*
  • Sebuah goroutine memantau event input ini dan hanya mengirim gambar saat diperlukan
  • Jika tidak ada event, penggunaan CPU turun ke 0 bahkan ketika klien masih terhubung
  • Saat menulis, penggunaan CPU berada di kisaran 10%

Perubahan firmware dan beban pemeliharaan

  • Aplikasi ini berbasis hacking, dan tantangan intinya adalah memisahkan antarmuka pengambilan gambar dari klien/renderer secara efektif
  • Implementasi sebelumnya memisahkan klien dan server sepenuhnya melalui definisi protobuf
  • Firmware reMarkable 3.3 merusak alat ini, dan rinciannya ada di GitHub issue 36
    • Saat itu perbaikannya hanya memengaruhi komponen klien
  • Firmware 3.6 juga, menurut GitHub issue 58, dapat membawa perubahan yang merusak
    • Dalam kasus ini, perbaikan yang lebih luas mungkin diperlukan
    • Namun, karena klien kini terintegrasi ke server dalam struktur yang mandiri, pembaruan perangkat bisa menjadi lebih sederhana
  • Aplikasi dan kode sumber tersedia di github.com/owulveryck/goMarkableStream

1 komentar

 
GN⁺ 2023-08-21
Opini Hacker News
  • Alat tahun 2021 untuk melakukan streaming layar tablet reMarkable ke laptop telah dipoles ulang dan dirilis, dan tulisan baru ini membahas secara mendalam proses peningkatan arsitektur, komponen, dan pengalaman pengguna
    Dari sudut pandang manajer produk, proses aktivasi disederhanakan dengan melihat bagaimana pengguna merasakannya, dibuat agar berjalan tanpa layanan lokal, dan penggunaan jaringan juga dioptimalkan

    • Terlihat seperti proyek yang keren. Setelah Ctrl-C lalu memulai ulang dengan ./goMarkableStream, ini berjalan sampai batas tertentu, tetapi waiting for reMarkable screen masih sering muncul dan layanannya tidak stabil
      Saya memasangnya setelah memperbarui reMarkable2 ke 3.5.2.1807, tetapi tidak ada respons saat menggambar di laptop, lembar kerja, maupun buku, dan log seperti read /dev/input/event2: file already closed, read /dev/input/event1: file already closed kadang terlihat
      Baik https://192.168.8.143:2001/ maupun https://10.11.99.1:2001/ menyajikan HTML dan kanvas, dan saya juga mencobanya di Chrome, Firefox, dan Brave
      Tampaknya ada batasan satu browser dan satu IP per stream, tetapi dengan alamat dan browser apa pun, kadang waiting for reMarkable screen tetap muncul. Setelah nohup ./goMarkableStream &, lalu menutup PuTTY dan memulai ulang klien, semua browser menjadi berada dalam keadaan yang sama, dan saat membuka https://10.11.99.1:2001/stream hasilnya mengembalikan too many requests. Saya penasaran bagaimana cara memulai ulang stream
    • Penasaran apakah ini juga bisa diimplementasikan lewat koneksi USB
  • Sebagai alternatif, saya sangat puas memakai SuperNote. Karena bisa melakukan screen mirroring, alat ini sangat bagus untuk menggambar diagram dengan cepat saat rapat
    Kekurangannya adalah SuperNote menjalankan web server kecil lalu diakses lewat Firefox, sehingga laptop dan SuperNote harus berada di jaringan yang sama. Di home office ini bukan masalah, tetapi bisa saja diblokir oleh kebijakan perusahaan
    Baik RM2 maupun SuperNote adalah alat yang hebat bagi orang yang suka menuangkan ide dengan pena dan kertas, rasanya cukup berbeda dari aplikasi atau dokumen teks, dan Anda juga bisa mencoret-coret catatan
    [0]: https://supernote.com/

    • Onyx Boox Note juga bekerja dengan baik, dan masih merilis pembaruan meski sudah lebih dari 5 tahun berlalu
      Namun saat membelinya, Anda harus siap menerima pelanggaran GPL. Meski sepenuhnya berbasis Android, mereka tidak merilis source code sistem operasinya
    • Saya sedang mencari tablet e-ink untuk pembaca ebook sekaligus mencatat, dan rekomendasinya membantu. Saya sedang bimbang antara Remarkable 2 dan Boox, dan penasaran seperti apa pengalaman pembaruan perangkat lunak SuperNote
      Saya khawatir akan membeli perangkat yang dalam 3–5 tahun ke depan tidak mendapat dukungan pembaruan fitur, atau setidaknya pembaruan keamanan
    • Setahu saya, SuperNote tidak mematuhi GPL untuk perangkat lunak yang mereka distribusikan bersama; saya penasaran apakah sikap mereka sudah berubah
    • Saya belum pernah mengalami masalah “harus berada di jaringan yang sama”, tetapi menambahkan fitur Ngrok native tampaknya pekerjaan sederhana yang hanya butuh beberapa menit. Dengan begitu streaming bisa dilakukan lewat internet
    • Penasaran bagaimana rasa menulis SuperNote dibandingkan dengan RM2
  • Rendering kanvas HTML bisa dibuat lebih cepat dengan memakai typed array seperti yang dijelaskan di sini: https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipu...

    • Terima kasih, akan saya lihat
  • Tulisan seperti inilah konten yang ingin saya lihat di sini. Saya suka bagaimana ChatGPT membantu mempelajari dan memecahkan masalah di area yang tidak terlalu dikuasainya, dan saya setuju dengan ungkapan “saya adalah developer dan ChatGPT adalah coder
    Pernyataan bahwa kesederhanaan pada kenyataannya kompleks juga benar

  • Saya rasa JPEG dipilih karena mudah diubah menjadi MJPEG, dan jika diserahkan ke pihak yang mendukungnya, decoding bisa ditangani nyaris gratis. Namun itu bisa menjadi faktor yang memberi beban besar pada CPU reMarkable
    JPEG lebih cocok untuk foto, sementara layar reMarkable lebih mirip ilustrasi, dan terlebih lagi bernuansa hitam-putih. Memakai format gambar umum lain seperti PNG atau sekadar kompresi RLE sederhana pun sepertinya akan memberi beban CPU yang lebih rendah

    • Secara ketat, reMarkable bukan monokrom, melainkan grayscale, dan seingat saya mendukung 16 tingkat abu-abu. Di aplikasi pendamping juga ada tinta berwarna, seperti pena yang terlihat biru/merah dan stabilo yang terlihat kuning/hijau
      Selain itu, format file proprietarinya berbasis input tulisan tangan, bukan bitmap
    • Alasan awal memilih JPEG memang benar. Namun karena itu saya memilih struktur klien/server, dan encoding dilakukan di laptop sebagai klien, bukan di tablet
      Setelah melakukan profiling, sebagian besar CPU dipakai untuk transfer data melalui kabel, jadi saya menambahkan kompresi. Sekarang penggunaan CPU rendah
  • Penasaran apakah Anda sudah mempertimbangkan cara hanya mengirim area framebuffer yang berubah. Itu bisa sangat mengurangi laju transfer data: https://github.com/pl-semiotics/mxc_epdc_fb_damage
    Proyek rM VNC juga melakukan itu, tetapi saya lebih suka pengalaman pengguna aplikasi ini yang tidak memerlukan perangkat lunak di sisi klien

    • Masalahnya, cara itu membutuhkan sejumlah analisis di perangkat, sementara saya ingin menjaga kodenya seminimal mungkin tidak invasif. Saya akan melihat apakah ada cara murah untuk menanganinya
  • Benar-benar keren dan saya ingin menyukai ReMarkable 2, tetapi sulit karena posisinya sebagai perangkat yang tidak aman: https://support.remarkable.com/s/article/Does-reMarkable-off...

    • Isi tautan tersebut berarti perangkat ini hanya memiliki tingkat keamanan fisik yang sama seperti kertas yang ingin digantikannya. Dengan kata lain, jika seseorang punya akses ke perangkatnya, ia bisa membacanya
      Ini bukan soal kerentanan software yang diketahui, seperti yang biasanya terbayang saat menyebut perangkat tidak aman yang terhubung ke jaringan
    • Secara tidak resmi, enkripsi direktori home berbasis gocryptfs dimungkinkan: https://github.com/RedTeamPentesting/remarkable-encryption
    • Software-nya juga untuk saat ini sangat terbatas. Sayang sekali secara resmi mereka tidak memungkinkan marketplace atau ekstensi digunakan di perangkat
    • Apakah ada e-book reader yang menyediakan enkripsi seluruh disk?
  • Ingin membaca lebih lanjut bagian “Awalnya saya mencoba mengompilasi klien ke WASM. Itu terlihat menjanjikan karena bisa memanfaatkan pengalaman pengembangan Go, tetapi saya menemui beberapa keterbatasan yang membutuhkan banyak modifikasi”

    • Masalah utamanya adalah library gRPC, dan dukungannya saat ini sangat terbatas. Selain itu, kompresi JPEG di Go lambat dan banyak memakai CPU
      Bahkan jika berhasil membuat stream MJPEG, cara menampilkannya juga menjadi masalah. Saya sempat mempertimbangkan pendekatan canvas, tetapi sulit mengakses backend canvas tanpa penyalinan besar antara WASM dan JS, dan ukurannya juga 2,5MB
      Pada akhirnya, jika bergantung pada WASM, sepertinya banyak operasi dasar gambar yang secara bawaan bisa diakses di JS, seperti rotasi gambar, harus diimplementasikan sendiri
  • Penasaran bagaimana tool ini berbeda dari streaming bawaan, yaitu fitur berbagi layar

    • Untuk memakai fitur bawaan, harus memasang aplikasi desktop, dan setahu saya tidak ada versi Linux
      https://support.remarkable.com/s/article/Screen-Share
      Solusi dalam tulisan ini tampaknya berjalan di Linux selama ada browser dengan fitur yang memadai
    • Perbedaan terbesarnya adalah sekarang tidak perlu instalasi klien. Cukup masukkan alamat reMarkable di browser untuk melihat isinya
    • Saya kira fitur ini sudah ada. Berbagi layar sudah cukup bagus, dan saya juga memakainya untuk live streaming
  • Saya suka reMarkable, tetapi ke depannya berharap mereka lebih fokus pada fitur streaming seperti ini daripada langganan yang tidak akan pernah saya bayar