<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohit Dubey</title>
    <description>The latest articles on DEV Community by Mohit Dubey (@mohit_dubey_5ac5787d1280a).</description>
    <link>https://dev.to/mohit_dubey_5ac5787d1280a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3476800%2F01f0cb13-f412-40a6-9f27-d7511fb09fd1.png</url>
      <title>DEV Community: Mohit Dubey</title>
      <link>https://dev.to/mohit_dubey_5ac5787d1280a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mohit_dubey_5ac5787d1280a"/>
    <language>en</language>
    <item>
      <title>How I Added Real-Time AR Filters and Custom Overlays to a Live Android Stream 🎭📱</title>
      <dc:creator>Mohit Dubey</dc:creator>
      <pubDate>Wed, 01 Apr 2026 10:59:06 +0000</pubDate>
      <link>https://dev.to/mohit_dubey_5ac5787d1280a/how-i-added-real-time-ar-filters-and-custom-overlays-to-a-live-android-stream-3goc</link>
      <guid>https://dev.to/mohit_dubey_5ac5787d1280a/how-i-added-real-time-ar-filters-and-custom-overlays-to-a-live-android-stream-3goc</guid>
      <description>&lt;p&gt;Live streaming is everywhere. But just streaming a plain camera feed feels boring in 2026. Viewers expect filters, effects, branding — the kind of stuff you see on TikTok and Instagram Live.&lt;/p&gt;

&lt;p&gt;In this post I'll show you how to build exactly that: an Android app that applies &lt;strong&gt;real-time DeepAR AR filters&lt;/strong&gt; (think viking helmets, neon devil horns, cat ears) and &lt;strong&gt;custom canvas overlays&lt;/strong&gt; (your logo, watermark, live badge) — and streams the whole thing live via &lt;strong&gt;Ant Media Server&lt;/strong&gt; over WebRTC with ~0.5s latency.&lt;/p&gt;

&lt;p&gt;The full sample project is on GitHub → &lt;a href="https://github.com/USAMAWIZARD/AntMedia-DeepAR-And-Overlay" rel="noopener noreferrer"&gt;AntMedia-DeepAR-And-Overlay&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What you'll build
&lt;/h2&gt;

&lt;p&gt;Two Activities, both streaming live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DeepARActivity&lt;/strong&gt; — real-time AR face filters powered by DeepAR SDK&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CustomCanvasActivity&lt;/strong&gt; — custom bitmap/text overlays drawn with Android Canvas&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you start, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Android Studio (Hedgehog or newer)&lt;/li&gt;
&lt;li&gt;A physical Android device (API 21+) — emulators don't do face tracking justice&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://developer.deepar.ai" rel="noopener noreferrer"&gt;DeepAR account&lt;/a&gt; and license key (free tier available)&lt;/li&gt;
&lt;li&gt;Git installed — Android Studio does &lt;strong&gt;not&lt;/strong&gt; include Git, install it separately from &lt;a href="https://git-scm.com/download/win" rel="noopener noreferrer"&gt;git-scm.com&lt;/a&gt; first&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1 — Clone the project
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/USAMAWIZARD/AntMedia-DeepAR-And-Overlay.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open Android Studio → &lt;strong&gt;File → Open&lt;/strong&gt; → select the cloned folder. Wait for Gradle sync to finish.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Good news:&lt;/strong&gt; The repo already has &lt;code&gt;settings.gradle&lt;/code&gt;, &lt;code&gt;build.gradle&lt;/code&gt;, and the &lt;code&gt;assets&lt;/code&gt; folder pre-configured. You don't need to add dependencies manually — they're already there.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 2 — Get your DeepAR license key
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sign up at &lt;a href="https://developer.deepar.ai" rel="noopener noreferrer"&gt;developer.deepar.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create a new project → Add Android App&lt;/li&gt;
&lt;li&gt;Enter your exact package name: &lt;code&gt;com.example.antmediacustomcanvasstreaming&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy the generated license key&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open &lt;code&gt;res/values/strings.xml&lt;/code&gt; and paste it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;resources&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"app_name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;AntMediaDeepAR&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"deepar_license_key"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;YOUR_LICENSE_KEY_HERE&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/resources&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;The license key is tied to your exact package name.&lt;/strong&gt; If the app crashes on launch, this is almost certainly why — double-check the package name matches exactly.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3 — Add the DeepAR effect files
&lt;/h2&gt;

&lt;p&gt;Here's a gotcha that isn't obvious from the code: &lt;code&gt;DeepARActivity&lt;/code&gt; references &lt;strong&gt;17 specific effect files&lt;/strong&gt; by name. If any of them are missing from your &lt;code&gt;assets&lt;/code&gt; folder, the app crashes with no clear error message.&lt;/p&gt;

&lt;p&gt;Go to &lt;a href="https://developer.deepar.ai/downloads" rel="noopener noreferrer"&gt;developer.deepar.ai/downloads&lt;/a&gt; and download the &lt;strong&gt;DeepAR Filter Pack (Legacy)&lt;/strong&gt; — this zip contains all the effects the code needs. Unzip it and copy the &lt;code&gt;.deepar&lt;/code&gt; files into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/src/main/assets/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code expects these files specifically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;viking_helmet.deepar
MakeupLook.deepar
Emotions_Exaggerator.deepar
Neon_Devil_Horns.deepar
Elephant_Trunk.deepar
flower_face.deepar
Humanoid.deepar
... (and more)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ Don't just download a couple — copy everything from the zip.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 4 — How the DeepAR integration works
&lt;/h2&gt;

&lt;p&gt;This is the interesting part. The key to making DeepAR and Ant Media work together is one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setVideoSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IWebRTCClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;StreamSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CUSTOM&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default &lt;code&gt;IWebRTCClient&lt;/code&gt; opens the camera itself. Setting &lt;code&gt;CUSTOM&lt;/code&gt; tells it: &lt;em&gt;"I'll push frames to you manually."&lt;/em&gt; That's what lets you insert DeepAR (or Canvas drawing) between the camera and the WebRTC encoder.&lt;/p&gt;

&lt;p&gt;Here's the flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CameraX → feedDeepAR() → DeepARRenderer (GLSurfaceView) → IWebRTCClient → Ant Media Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;IWebRTCClient&lt;/code&gt; is set up like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;webRTCClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;IWebRTCClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setServerUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wss://test.antmedia.io/LiveApp/websocket"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setActivity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setVideoSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IWebRTCClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;StreamSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CUSTOM&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setWebRTCListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;createWebRTCListener&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setInitiateBeforeStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CameraX feeds each frame into DeepAR via &lt;code&gt;receiveFrame()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;deepAR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;receiveFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;buffers&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;currentBuffer&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getImageInfo&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getRotationDegrees&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;lensFacing&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;CameraSelector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LENS_FACING_FRONT&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// mirror for selfie&lt;/span&gt;
    &lt;span class="nc"&gt;DeepARImageFormat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;YUV_420_888&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;uPixelStride&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DeepAR processes the frame (applies the AR effect using GPU), then &lt;code&gt;DeepARRenderer&lt;/code&gt; pushes the result to the WebRTC client.&lt;/p&gt;

&lt;p&gt;Switching effects mid-stream is one line and doesn't interrupt the broadcast at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;deepAR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;switchEffect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"effect"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"file:///android_asset/viking_helmet.deepar"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5 — Custom Canvas overlays
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;CustomCanvasActivity&lt;/code&gt; takes a different approach — no DeepAR needed. It grabs each camera frame as a &lt;code&gt;Bitmap&lt;/code&gt; and paints your graphics on top using Android's &lt;code&gt;Canvas&lt;/code&gt; API before pushing to &lt;code&gt;IWebRTCClient&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Bitmap&lt;/span&gt; &lt;span class="nf"&gt;addOverlay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Bitmap&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Bitmap&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Bitmap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ARGB_8888&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Canvas&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Logo — bottom-right corner&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWidth&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;overlayBitmap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getWidth&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getHeight&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;overlayBitmap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getHeight&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;drawBitmap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overlayBitmap&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lx&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ly&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Text watermark — top-left with drop shadow&lt;/span&gt;
    &lt;span class="nc"&gt;Paint&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Paint&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setColor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WHITE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTextSize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAntiAlias&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setShadowLayer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BLACK&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;drawText&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@YourBrand"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mutable&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same &lt;code&gt;StreamSource.CUSTOM&lt;/code&gt; pattern applies — same builder, same &lt;code&gt;sendFrameForProcessing()&lt;/code&gt; call.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6 — Run it
&lt;/h2&gt;

&lt;p&gt;Connect your Android phone via USB, enable USB Debugging, and hit ▶ Run in Android Studio.&lt;/p&gt;

&lt;p&gt;Grant camera and microphone permissions when prompted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The repo already points to Ant Media's public test server&lt;/strong&gt; — you don't need your own server to test this. Just tap &lt;strong&gt;Start&lt;/strong&gt; in the app, then open this URL in your browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://test.antmedia.io/LiveApp/player.html?id=test1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see your AR-filtered live stream playing in the browser within a second. 🎉&lt;/p&gt;

&lt;p&gt;When you're ready to use your own server, just swap this line in &lt;code&gt;setupStreamingAndPreview()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setServerUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wss://YOUR-SERVER/LiveApp/websocket"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Things that tripped me up (so they don't trip you up)
&lt;/h2&gt;

&lt;p&gt;After going through this end-to-end, here's what I wish I'd known:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install Git before you do anything else.&lt;/strong&gt;&lt;br&gt;
Android Studio doesn't come with Git. If you run &lt;code&gt;git clone&lt;/code&gt; and get &lt;code&gt;'git' is not recognized&lt;/code&gt;, go install it from git-scm.com first, then reopen your terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Filter Pack zip is not obvious.&lt;/strong&gt;&lt;br&gt;
The downloads page shows "DeepAR Android SDK" which is the SDK itself. The effect files are in a separate "Filter Pack (Legacy)" download. Easy to miss, causes a silent crash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Missing effect files = instant crash, no clear error.&lt;/strong&gt;&lt;br&gt;
The crash log shows an EGL surface error which looks completely unrelated to missing files. If your DeepAR activity crashes immediately, check your assets folder first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The test server is genuinely useful.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;wss://test.antmedia.io&lt;/code&gt; is Ant Media's public test server — it's real, it works, and it means you can verify your stream end-to-end without any server setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Use a physical device for DeepAR.&lt;/strong&gt;&lt;br&gt;
Emulator cameras are simulated and face tracking won't work meaningfully. The custom canvas overlay works fine on emulators though.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to build next
&lt;/h2&gt;

&lt;p&gt;Once you have this running, some natural next steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Filter picker UI&lt;/strong&gt; — a horizontal RecyclerView that calls &lt;code&gt;deepAR.switchEffect()&lt;/code&gt; on tap&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local recording&lt;/strong&gt; — &lt;code&gt;deepAR.startVideoRecording()&lt;/code&gt; saves an AR copy to the gallery simultaneously while streaming&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom effects&lt;/strong&gt; — build your own branded AR filter in &lt;a href="https://www.deepar.ai/creator-studio" rel="noopener noreferrer"&gt;DeepAR Creator Studio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your own server&lt;/strong&gt; — sign up for &lt;a href="https://antmedia.io" rel="noopener noreferrer"&gt;Ant Media's free 14-day trial&lt;/a&gt; to get a cloud server with your own stream URLs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📦 Sample repo: &lt;a href="https://github.com/USAMAWIZARD/AntMedia-DeepAR-And-Overlay" rel="noopener noreferrer"&gt;github.com/USAMAWIZARD/AntMedia-DeepAR-And-Overlay&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📖 Full tutorial: &lt;a href="https://antmedia.io/deepar-and-custom-overlay-with-ant-media-android-sdk/" rel="noopener noreferrer"&gt;antmedia.io/deepar-and-custom-overlay-with-ant-media-android-sdk&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔑 DeepAR developer portal: &lt;a href="https://developer.deepar.ai" rel="noopener noreferrer"&gt;developer.deepar.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🖥️ Ant Media docs: &lt;a href="https://antmedia.io/docs" rel="noopener noreferrer"&gt;antmedia.io/docs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Have questions or hit a different error? Drop it in the comments — happy to help. 👇&lt;/p&gt;

</description>
      <category>android</category>
      <category>webrtc</category>
      <category>antmediaserver</category>
    </item>
    <item>
      <title>WebRTC Browser Support &amp; Compatibility</title>
      <dc:creator>Mohit Dubey</dc:creator>
      <pubDate>Wed, 01 Oct 2025 10:56:20 +0000</pubDate>
      <link>https://dev.to/mohit_dubey_5ac5787d1280a/webrtc-browser-support-compatibility-5co</link>
      <guid>https://dev.to/mohit_dubey_5ac5787d1280a/webrtc-browser-support-compatibility-5co</guid>
      <description>&lt;p&gt;&lt;strong&gt;WebRTC (Web Real-Time Communication) is a set of open-source standards, APIs, and protocols developed by the IETF and W3C to enable real-time communication directly inside browsers and applications.&lt;/strong&gt; Its significance lies in allowing seamless video, audio, and data transfer without requiring external plugins, legacy technologies (such as Flash), or additional installations. Learn &lt;a href="https://antmedia.io/webrtc-browser-support/" rel="noopener noreferrer"&gt;more about what WebRTC&lt;/a&gt; is and how it works.&lt;/p&gt;

</description>
      <category>dev2</category>
      <category>webrtc</category>
    </item>
    <item>
      <title>What is WebRTC and how does it work?</title>
      <dc:creator>Mohit Dubey</dc:creator>
      <pubDate>Wed, 03 Sep 2025 06:13:17 +0000</pubDate>
      <link>https://dev.to/mohit_dubey_5ac5787d1280a/what-is-webrtc-and-how-does-it-work-11i</link>
      <guid>https://dev.to/mohit_dubey_5ac5787d1280a/what-is-webrtc-and-how-does-it-work-11i</guid>
      <description>&lt;p&gt;WebRTC stands for Web Real-Time Communications. It is a very exciting, powerful, and highly disruptive cutting-edge technology and streaming protocol.&lt;/p&gt;

&lt;p&gt;WebRTC is HTML5 compatible, and you can use it to add real-time media communications directly between browsers and devices. One of the main advantages of using WebRTC is that it does not require any browser plugins as a prerequisite.&lt;/p&gt;

&lt;p&gt;Webrtc is progressively becoming supported by all major modern browser vendors, including Safari, Google Chrome, Firefox, Opera, and others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://antmedia.io/what-is-webrtc-and-how-webrtc-works/" rel="noopener noreferrer"&gt;Tutorial Source&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it includes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;What is WebRTC?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;History of WebRTC&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WebRTC Components&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WebRTC Video Streaming&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Types of WebRTC Servers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is great for anyone who is looking to get started with WebRTC &amp;amp; learn about it.&lt;br&gt;
Feel free to check it out, give it a ⭐️ if it helps, and let me know what you think!&lt;/p&gt;

</description>
      <category>webrtc</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
