Skip to content

Instantly share code, notes, and snippets.

@aphexcx
Created January 24, 2026 08:22
Show Gist options
  • Select an option

  • Save aphexcx/e4521fb10b00e32dca5b57b607ca3319 to your computer and use it in GitHub Desktop.

Select an option

Save aphexcx/e4521fb10b00e32dca5b57b607ca3319 to your computer and use it in GitHub Desktop.
M20 Relay Architecture Diagrams
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 280" fill="none">
<defs>
<linearGradient id="jabraGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#F59E0B;stop-opacity:1" />
<stop offset="100%" style="stop-color:#D97706;stop-opacity:1" />
</linearGradient>
<linearGradient id="pulseGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#EC4899;stop-opacity:1" />
<stop offset="100%" style="stop-color:#DB2777;stop-opacity:1" />
</linearGradient>
<linearGradient id="gstGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#8B5CF6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#7C3AED;stop-opacity:1" />
</linearGradient>
<linearGradient id="rtcAudioGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#10B981;stop-opacity:1" />
<stop offset="100%" style="stop-color:#059669;stop-opacity:1" />
</linearGradient>
<linearGradient id="browserAudioGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#3B82F6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1D4ED8;stop-opacity:1" />
</linearGradient>
<filter id="shadow3" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="1" dy="2" stdDeviation="2" flood-opacity="0.15"/>
</filter>
<marker id="audioArrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#10B981"/>
</marker>
<marker id="audioArrowRev" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
<polygon points="0 0, 8 3, 0 6" fill="#3B82F6"/>
</marker>
</defs>
<!-- Title -->
<text x="400" y="25" text-anchor="middle" font-family="system-ui, sans-serif" font-size="18" font-weight="bold" fill="#1F2937">Audio Streaming Pipeline (Bidirectional)</text>
<!-- CAPTURE ROW (Dog → Browser) -->
<text x="40" y="70" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="#10B981">CAPTURE (Dog → Browser)</text>
<!-- Jabra Mic -->
<g filter="url(#shadow3)">
<rect x="30" y="85" width="100" height="70" rx="8" fill="url(#jabraGrad)"/>
<text x="80" y="115" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">Jabra 510</text>
<text x="80" y="132" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">USB Mic</text>
<text x="80" y="147" text-anchor="middle" font-family="system-ui, sans-serif" font-size="8" fill="rgba(255,255,255,0.7)">48kHz</text>
</g>
<path d="M135 120 L165 120" stroke="#10B981" stroke-width="2" marker-end="url(#audioArrow)"/>
<!-- PulseAudio -->
<g filter="url(#shadow3)">
<rect x="170" y="85" width="100" height="70" rx="8" fill="url(#pulseGrad)"/>
<text x="220" y="115" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">PulseAudio</text>
<text x="220" y="132" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">Source</text>
</g>
<path d="M275 120 L305 120" stroke="#10B981" stroke-width="2" marker-end="url(#audioArrow)"/>
<!-- GStreamer -->
<g filter="url(#shadow3)">
<rect x="310" y="85" width="100" height="70" rx="8" fill="url(#gstGrad)"/>
<text x="360" y="115" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">GStreamer</text>
<text x="360" y="132" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">Opus Encode</text>
</g>
<path d="M415 120 L445 120" stroke="#10B981" stroke-width="2" marker-end="url(#audioArrow)"/>
<!-- WebRTC Audio -->
<g filter="url(#shadow3)">
<rect x="450" y="85" width="100" height="70" rx="8" fill="url(#rtcAudioGrad)"/>
<text x="500" y="115" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">WebRTC</text>
<text x="500" y="132" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">Audio Track</text>
</g>
<path d="M555 120 L585 120" stroke="#10B981" stroke-width="2" marker-end="url(#audioArrow)"/>
<!-- Browser Speaker -->
<g filter="url(#shadow3)">
<rect x="590" y="85" width="100" height="70" rx="8" fill="url(#browserAudioGrad)"/>
<text x="640" y="115" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">Browser</text>
<text x="640" y="132" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">Speaker Out</text>
</g>
<!-- PLAYBACK ROW (Browser → Dog) -->
<text x="40" y="190" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="#3B82F6">PLAYBACK (Browser → Dog)</text>
<!-- Browser Mic -->
<g filter="url(#shadow3)">
<rect x="590" y="205" width="100" height="70" rx="8" fill="url(#browserAudioGrad)"/>
<text x="640" y="235" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">Browser</text>
<text x="640" y="252" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">Mic Input</text>
</g>
<path d="M585 240 L555 240" stroke="#3B82F6" stroke-width="2" marker-end="url(#audioArrowRev)"/>
<!-- WebRTC Audio Rev -->
<g filter="url(#shadow3)">
<rect x="450" y="205" width="100" height="70" rx="8" fill="url(#rtcAudioGrad)"/>
<text x="500" y="235" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">WebRTC</text>
<text x="500" y="252" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">Audio Track</text>
</g>
<path d="M445 240 L415 240" stroke="#3B82F6" stroke-width="2" marker-end="url(#audioArrowRev)"/>
<!-- GStreamer Rev -->
<g filter="url(#shadow3)">
<rect x="310" y="205" width="100" height="70" rx="8" fill="url(#gstGrad)"/>
<text x="360" y="235" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">GStreamer</text>
<text x="360" y="252" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">Opus Decode</text>
</g>
<path d="M305 240 L275 240" stroke="#3B82F6" stroke-width="2" marker-end="url(#audioArrowRev)"/>
<!-- PulseAudio Rev -->
<g filter="url(#shadow3)">
<rect x="170" y="205" width="100" height="70" rx="8" fill="url(#pulseGrad)"/>
<text x="220" y="235" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">PulseAudio</text>
<text x="220" y="252" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">Sink</text>
</g>
<path d="M165 240 L135 240" stroke="#3B82F6" stroke-width="2" marker-end="url(#audioArrowRev)"/>
<!-- Jabra Speaker -->
<g filter="url(#shadow3)">
<rect x="30" y="205" width="100" height="70" rx="8" fill="url(#jabraGrad)"/>
<text x="80" y="235" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="bold" fill="white">Jabra 510</text>
<text x="80" y="252" text-anchor="middle" font-family="system-ui, sans-serif" font-size="9" fill="rgba(255,255,255,0.8)">USB Speaker</text>
</g>
<!-- Latency note -->
<rect x="700" y="150" width="90" height="40" rx="6" fill="#ECFDF5" stroke="#10B981"/>
<text x="745" y="168" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" font-weight="bold" fill="#059669">Target</text>
<text x="745" y="182" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#059669">~50ms</text>
</svg>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment