Dots

ブログとか

アスキーアートのビデオチャット

アスキーアートのビデオチャットを作った。 サイトのURLは /pages/aachat/


概要

AA電話は、WebRTCを使用してリアルタイムでビデオをASCIIアートに変換し、相手と通信するWebアプリケーション。

音声は普通に通話できるけど、通常の映像を無駄にテキストに変換して表示します。

処理的には普通に映像を表示するほうが楽だが、を敢えてAAで表示することにより、低解像度であることを誤魔化しつつ帯域を節約することができる。

使ってみるとわかるが、相手の表情がわからないため、ずっと喋ってないと不安になる。

技術構成

使用技術

システム構成図

%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor': '#4a90e2', 'primaryTextColor': '#ffffff', 'primaryBorderColor': '#6bb6ff', 'lineColor': '#8cc8ff', 'background': '#2d3748', 'mainBkg': '#2d3748', 'secondBkg': '#4a5568'}}}%%
graph TB
    subgraph "ブラウザA (ホスト)"
        A1[カメラ/マイク] --> A2[MediaStream]
        A2 --> A3[Canvas処理]
        A3 --> A4[ASCII変換]
        A4 --> A5[表示]
        A2 --> A6[PeerConnection]
    end
    
    subgraph "Public Piping Server(※)"
        S1[シグナリング]
    end
    
    subgraph "ブラウザB (ゲスト)"
        B1[カメラ/マイク] --> B2[MediaStream]
        B2 --> B3[Canvas処理]
        B3 --> B4[ASCII変換]
        B4 --> B5[表示]
        B2 --> B6[PeerConnection]
    end
    
    A6 -.PUT/GET<br/>(暗号化データ).- S1
    B6 -.PUT/GET<br/>(暗号化データ).- S1
    A6 <==>|WebRTC P2P接続| B6

    classDef hostStyle fill:#4a90e2,stroke:#6bb6ff,stroke-width:2px,color:#ffffff
    classDef guestStyle fill:#9f7aea,stroke:#b794f6,stroke-width:2px,color:#ffffff
    classDef serverStyle fill:#ed8936,stroke:#f6ad55,stroke-width:2px,color:#ffffff

    class A1,A2,A3,A4,A5,A6 hostStyle
    class B1,B2,B3,B4,B5,B6 guestStyle
    class S1 serverStyle

主要機能

1. WebRTC通信

2. ASCII アート変換

3. デバイス管理

通信フロー

%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor': '#4a90e2', 'primaryTextColor': '#ffffff', 'primaryBorderColor': '#6bb6ff', 'lineColor': '#8cc8ff', 'secondaryColor': '#ed8936', 'tertiaryColor': '#9f7aea', 'background': '#2d3748', 'mainBkg': '#2d3748', 'secondBkg': '#4a5568', 'actorBkg': '#4a90e2', 'actorTextColor': '#ffffff', 'actorLineColor': '#6bb6ff', 'signalColor': '#ffffff', 'signalTextColor': '#ffffff', 'c0': '#4a90e2', 'c1': '#9f7aea', 'c2': '#ed8936'}}}%%
sequenceDiagram
    participant H as ホスト
    participant P as Public Piping Server
    participant G as ゲスト
    
    H->>H: カメラ起動・AA変換開始
    H->>P: PUT /aachat/{keyword}<br/>暗号化されたOffer(SDP)+sessionToken
    
    G->>G: カメラ起動・AA変換開始
    loop ポーリング(2秒間隔)
        G->>P: GET /aachat/{keyword}
        P-->>G: Offerデータ+sessionToken取得
    end
    
    G->>P: PUT /aachat/{keyword}/{sessionToken}/answer<br/>暗号化されたAnswer(SDP)
    
    loop ポーリング(2秒間隔)
        H->>P: GET /aachat/{keyword}/{sessionToken}/answer
        P-->>H: Answerデータ取得
    end
    
    par ICE候補の交換
        H->>P: PUT /aachat/{keyword}/{sessionToken}/ice-host<br/>ホストのICE候補
        loop ポーリング
            G->>P: GET /aachat/{keyword}/{sessionToken}/ice-host
            P-->>G: ホストのICE候補取得
        end
    and
        G->>P: PUT /aachat/{keyword}/{sessionToken}/ice-guest<br/>ゲストのICE候補
        loop ポーリング
            H->>P: GET /aachat/{keyword}/{sessionToken}/ice-guest
            P-->>H: ゲストのICE候補取得
        end
    end
    
    Note over H,G: P2P接続確立後は Public Piping Server 不要
    H->>G: ビデオ/オーディオ直接送信
    G->>H: ビデオ/オーディオ直接送信
    
    Note over H,G: 各自でローカル変換
    H->>H: 受信映像をAA変換
    G->>G: 受信映像をAA変換

Piping Server の活用方法

Piping Serverは本来一時的なデータ転送を行うものですが、以下の方法でWebRTCシグナリングに転用しています:

  1. エンドポイント設計:
    • 初回のOffer: /aachat/{keyword}
    • 以降の通信: /aachat/{keyword}/{sessionToken}/*
  2. sessionToken: 16文字のランダム文字列でセッションを分離
  3. HTTP PUT/GET: データの保存と取得
  4. ポーリング: リアルタイム通知がないため2秒間隔でポーリング
  5. 暗号化: キーワードをキーとしたXOR暗号化でデータを保護
  6. 一時的なデータ保存: Offer/Answer/ICE候補を一時的に保存

制限事項