1 puan yazan GN⁺ 2025-12-24 | 1 yorum | WhatsApp'ta paylaş
  • Helix, bulutta otonom kodlama ajanlarının çalıştığı ekranı kullanıcıya gösteren bir AI platformu ve bunun için kararlı uzak ekran aktarımı kritik önem taşıyor
  • Kurumsal ağlardaki UDP engellemesi ve güvenlik duvarı kısıtlamaları nedeniyle WebRTC tabanlı yayın başarısız olunca ekip, WebSocket tabanlı bir H.264 hattı kurdu; ancak kararsız Wi-Fi ortamlarında gecikme ciddi hale geldi
  • Karmaşık kodlama/kod çözme yapısı yerine, basitçe JPEG ekran görüntülerini HTTP üzerinden periyodik olarak göndermenin çok daha kararlı ve verimli olduğunu fark ettiler
  • Bu yöntem daha az bant genişliği kullanıyor, bozuk kareleri kurtarmayı gerektirmiyor ve ağ kalitesine göre görüntü kalitesini ve kare hızını otomatik olarak ayarlıyor
  • Sonuç olarak Helix, iyi bağlantılarda H.264, kötü bağlantılarda ise JPEG polling'e geçen hibrit bir yapı benimsedi ve basit ama pratik bir uzak yayın sistemi oluşturdu

Helix'in yayın sorunları ve kısıtları

  • Helix, bulut sandbox'larında çalışan AI kodlama ajanının ekranını gerçek zamanlı paylaşması gereken bir platform
    • Kullanıcılar, tıpkı uzak masaüstünde olduğu gibi, yapay zekanın kod yazma sürecini izliyor
  • Başlangıçta WebRTC kullanıldı, ancak kurumsal ağların UDP'yi engellemesi nedeniyle bağlantı kurulamıyordu
    • TURN sunucuları, STUN/ICE, özel portlar gibi çözümlerin tümü güvenlik duvarı politikaları tarafından engellendi
  • Bunun üzerine ekip, yalnızca HTTPS (443 portu) kullanan WebSocket tabanlı bir H.264 yayın hattını doğrudan kendisi geliştirdi
    • Donanım kodlama için GStreamer + VA-API, tarayıcı tarafında kod çözme için WebCodecs kullanıldı
    • 60fps, 40Mbps ve 100ms'nin altında gecikme elde edildi

Ağ gecikmesi ve performans düşüşü

  • Kafeler gibi kararsız ağ ortamlarında görüntünün donması veya onlarca saniyelik gecikme sorunları yaşandı
    • TCP tabanlı WebSocket'te paket kaybı olduğunda kareler sırayla geciktiği için gerçek zamanlılık bozuldu
  • Bit hızı düşürülse bile gecikme çözülmedi, yalnızca görüntü kalitesi azaldı
  • Yalnızca keyframe gönderme yöntemi de denendi, ancak Moonlight protokolü P-frame gerektirdiği için başarısız oldu

JPEG ekran görüntüsü yönteminin keşfi

  • Hata ayıklama sırasında /screenshot?format=jpeg&quality=70 endpoint'i çağrılınca anında net bir görüntü yüklendi
    • 150KB boyutundaki tek bir JPEG, gecikme olmadan gösterildi
  • Ekran görüntüsünü basitçe tekrarlanan HTTP istekleriyle yenileyince yaklaşık 5fps düzeyinde akıcı ekran güncellemesi mümkün oldu
  • Sonunda karmaşık video hattı yerine, periyodik JPEG isteği (fetch döngüsü) yaklaşımına geçildi

JPEG yönteminin avantajları

  • H.264'e göre temel karşılaştırmalar
    • Bant genişliği: H.264 sabit 40Mbps, JPEG ise 100~500Kbps arasında değişiyor
    • Durum yönetimi: H.264 duruma bağımlı, JPEG ise tamamen bağımsız karelerden oluşuyor
    • Kurtarılabilirlik: H.264'te keyframe beklemek gerekiyor, JPEG'de ise bir sonraki kareyle anında toparlanılıyor
    • Karmaşıklık: H.264 aylar süren geliştirme gerektirdi, JPEG ise birkaç satırlık fetch() döngüsüyle uygulandı
  • Ağ kalitesi kötüleştikçe, basit JPEG yaklaşımı daha kararlı ve daha verimli hale geliyor

Hibrit geçiş yapısı

  • Helix, iki yöntemi RTT (gidiş-dönüş gecikmesi) değerine göre otomatik değiştiriyor
    1. RTT < 150ms → H.264 yayını
    2. RTT > 150ms → JPEG polling
    3. Bağlantı toparlandığında, kullanıcı tıklayarak yeniden geçiş yapıyor
  • Girdi olayları (klavye/fare) WebSocket üzerinden gönderilmeye devam ettiği için etkileşim korunuyor
  • Sunucu, {"set_video_enabled": false} mesajıyla video aktarımını durdurup ekran görüntüsü moduna geçiyor

Kararsız geçiş (oscillation) sorunu ve çözümü

  • Aktarım durduktan sonra WebSocket trafiği azalınca gecikme düşüyor ve sistemin otomatik olarak yeniden video moduna geçmesine yol açan sonsuz döngü oluşuyordu
  • Çözüm: Ekran görüntüsü moduna girildikten sonra, kullanıcı tıklayana kadar bu mod sabit tutuluyor
    • Arayüzde “Bant genişliğinden tasarruf etmek için video duraklatıldı” mesajı gösteriliyor

JPEG desteği sorunu ve derleme süreci

  • Wayland için ekran görüntüsü aracı grim'in Ubuntu'nun varsayılan paketinde JPEG desteği devre dışı bırakılmış
    • grim -t jpeg çalıştırıldığında “jpeg support disabled” hatası veriliyor
  • Bunu çözmek için Dockerfile içinde libjpeg-turbo8-dev eklenerek grim doğrudan kaynaktan derlendi

Nihai mimari

  • İyi bağlantı: 60fps H.264, donanım hızlandırmalı
  • Kötü bağlantı: 2~10fps JPEG polling, tam güvenilirlik
  • Ekran görüntüsü kalitesi, aktarım süresine göre otomatik ayarlanıyor
    • 500ms'yi aşarsa kalite -10%, 300ms'nin altındaysa +5%, minimum 2fps korunuyor

Ana çıkarımlar

  1. Basit çözüm, karmaşık sistemden daha iyidir — 3 aylık H.264 geliştirmesinden daha pratik olan şey, 2 saatlik JPEG hack'i oldu
  2. Graceful degradation, kullanıcı deneyiminin anahtarıdır
  3. WebSocket girdi aktarımı için ideal, görüntü aktarımı içinse zorunlu değil
  4. Ubuntu paketlerinde özellik eksik olabilir — gerekirse doğrudan derlemek gerekir
  5. Optimizasyondan önce ölçüm şart — karmaşık yayın altyapısı tek çözüm olmayabilir

Açık kaynak olarak yayınlandı

  • Helix açık kaynak olarak sunuluyor ve temel uygulama bileşenleri şunlar
    • api/cmd/screenshot-server/main.go — ekran görüntüsü sunucusu
    • MoonlightStreamViewer.tsx — uyarlanabilir istemci mantığı
    • websocket-stream.ts — video geçiş kontrolü
  • Helix, gerçek ortamlarda da çalışan yapay zeka altyapısı hedefiyle geliştiriliyor

1 yorum

 
GN⁺ 2025-12-24
Hacker News görüşleri
  • Ağ kötü olduğunda JPEG'in daha iyi çalışması UDP yüzünden değil, TCP'nin uygulanma biçimi yüzünden
    JPEG, buffering ya da congestion control sorunlarını çözmez. Muhtemelen kare iletimini en aza indiren bir yapıyla uygulanmış
    h.264, JPEG'den kodlama verimliliği açısından daha iyidir. Aynı boyutta ise h.264 IDR frame daha iyi kalite verebilir
    Temel sorun, bant genişliği tahmininin olmaması. TCP ortamında da başlangıç bant genişliği probing'i ve iletim gecikmesi algılamasıyla bitrate ayarlanabilir
    Mümkünse WebRTC kullanmak daha iyi, firewall aşma amacıyla ise WebSocket tercih edilmeli

    • Yazıdaki polling kodunda, önceki JPEG indirme bitmeden bir sonraki istek gönderilmiyordu. UDP olmasa da böyle bir döngü mümkündür
    • Muhtemelen frame'leri tamamen serileştirip aynı anda yalnızca bir tane isteyen bir yapı vardı ya da her seferinde yeni bir GET isteğiyle yeni bağlantı açılıyordu
    • İlginç olan, görsel olarak aynı JPEG bile boyut olarak %10~15 seviyesine düşebilir. 2000'lerin sonlarında web performansı optimizasyonu yaparken bu tür verimlilik kazanımları çok tatmin ediciydi
  • Yazının biçim sorunlarını ya da LLM tarzını bir kenara bıraksak bile, genel içerikte çok fazla yanlış var
    10Mbps statik bir ekran için yeterli olmalı. Sorun, encoding ayarlarının yanlış olması ya da encoder kalitesinin düşük olması
    “Sadece keyframe gönderelim” yaklaşımı verimsiz; bunun yerine kısa keyframe aralığı ayarlanabilir
    Sonuçta sorun, tüm stream'i tek bir TCP bağlantısından iten yapı. Bu tür durumlar için DASH gibi çözümler zaten var

    • Yapay zeka yazısı gibi duran içeriklerin neden üste çıktığını anlamıyorum. Özensiz yazılmış metinleri okumak zaman kaybı gibi geliyor
    • Apple tarafında DASH desteklenmiyor. HLS bir alternatif olabilir ama ffmpeg olmadan uygulaması çok zor
    • Bu yazıda aslında neredeyse hiç LLM tarzı hissetmiyorum. Dayanaksız eleştiri ikna edici değil
    • Mevcut araçları öğrenmenin zaman ve maliyeti yüksek olduğu için, “yanlış bir yeniden icat” bile duruma göre daha verimli olabilir
  • VNC'nin 1998'den beri yaptığı yönteme bakmak iyi olabilir
    İstemci çekme modelini korurken framebuffer'ı tile bazında bölüp, sadece değişen kısımları ileten bir yapı kullanıyor
    Statik kod ekranlarında bant genişliğini ciddi biçimde azaltabilir. Scroll algılama da eklenirse daha verimli olur

    • Birçok öneri içinde en gerçekçi başlangıç noktası bu gibi görünüyor. 40Mbps'yi varsayılan almak, soruna yaklaşımın baştan hatalı olduğunu düşündürüyor
    • Yazıda acemilik hissediliyordu. Bu yaklaşımın açık kaynak olarak da mümkün olup olmadığını merak ediyorum
    • Önce neko projesine bakılmasını öneririm. VNC'ye göre bağlantı gecikmesi ve backpressure sorunlarını çok daha iyi ele alıyor
    • VNC yaklaşımını kopyalamak en doğal ilk deneme gibi görünüyor. Moonlight gibi oyun odaklı düşük gecikmeli çözümler kullanmak ise tersine uygun değil
  • Daha önce video encoding ile uğraşmıştım; 40Mbps Blu-ray düzeyinde kalite demek
    Basit metin akışı için aşırı fazla. Claude ile konuşunca 30FPS, 2 saniyelik GOP ve ortalama 1Mbps civarının yeterli olduğu sonucuna vardım
    En kötü durumda bile 1.2Mbps yeterince istikrarlı kalite sağlayabilir

  • Bu yazının temel sorunu, h.264 için minimum bant genişliğini çok yüksek ayarlamış olması
    H.264, JPEG'den çok daha verimli. 1Mbps'den başlayıp oradan ayarlamak gerekirdi
    Sadece keyframe kullanmak ise tersine verimsizdir

    • Yazıda “10Mbps'ye düşürünce 30 saniye gecikme oldu” deniyordu ama bu muhtemelen encoding ayarlarıyla ilgili bir sorun
    • JPEG tarafında da buffering ile oynatma kuyruğu oluşturulursa takılma sorunu hafifletilebilir. Modern player'lar ağ kalitesini gerçek zamanlı izliyor
  • Ben olsam tamamen farklı yaklaşırdım
    10Mbps aşırı yüksek ve YouTube'daki kodlama videoları 1080p'de bile 0.6Mbps civarında. Gayet net görünüyor
    Bunun yerine 1fps'ye düşürmek ya da keyframe aralığını ayarlamak daha mantıklı olurdu

    • Yazının üslubu ve mantık akışı LLM kokuyor. Kod da muhtemelen aynı seviyededir
    • 1fps yetersiz olabilir. Tüm frame'leri keyframe yapan bir ayar gerekir
    • Ama bazı insanlar için YouTube kalitesi bile katlanılamayacak kadar rahatsız edici olabilir
  • Tarayıcıya gerçek zamanlı video stream etmek gerçekten acı verici bir iş
    JPEG screenshot'lar iyi çalışıyorsa öyle bırakmak daha iyi
    gstreamer ya da Moonlight gibi stack'lerde backpressure ve hata yayılımını anlamadan debug etmek cehennemdir
    NVIDIA Video Codec SDK + WebSocket + MediaSource Extensions birleşimi gerçekçi bir alternatif
    Ama yazı LLM üretimiyse, yazarın bu iç yapıları anlamaya niyeti yok gibi duruyor

    • Bu kadar karmaşık sistemleri tek bir amaç için ele almak gerektiğinde, LLM'ler aslında faydalı olabilir
  • Eskiden her 5 saniyede bir screenshot alan bir program kullanmıştım, sabit disk çok hızlı doluyordu
    Görsellerin çoğunun aynı olduğunu fark edip sadece değişen kısımları kaydeden bir algoritma düşünmeye başladım
    Sonra aslında video sıkıştırmayı yeniden icat ettiğimi fark ettim
    ffmpeg ile tek satırda çözdüm ve depolama alanının %98'ini tasarruf ettim

  • LLM'nin yazı yazmasını 40Mbps ile stream etmek anormal derecede aşırı bant genişliği kullanmak demek

    • Üstelik 60fps ile “bilgisayarın yazı yazdığı sahneyi” izlemek de tuhaf. Sorun alanını hiç anlamayan bir yaklaşım gibi görünüyor
  • HN'de iyi cevap almanın tek yolu yanlış bir yazı paylaşmak
    Yanlış ama ilginç bir yazı, bence tartışma çıkarmak için kusursuz dengeyi yakalayan bir örnek