Skip to content

new feature: receiving udp video strem from cheap toys with wifi cam's #187

Open

Description

@CatRovacer

Request for new new feature: receiving udp video strem from cheap toys with wifi cam's

Receiving and playing back video streams from cheap toys equipped with Wi‑Fi cameras. The camera up an access point. We connect to it. UDP stream. Now decoder only in Buffering state.

Activity

  1. compot-dev commented on Oct 15, 2026

    @compot-dev
    Collaborator

    Thanks for the request! We looked into it. Toys with a FLOW-UFO-xxxxxx access point (BL60x camera, the KY UFO app) don't send plain RTP or raw UDP video. The drone waits for a probe from the client on 192.168.169.1:8800, then sends MJPEG frames cut into 1 KB fragments, and the client has to keep acknowledging them. The decoder never sends that probe, so it stays in Buffering.

    We'll add this protocol as a new transport (video only, no flight control) and build a test APK from a separate branch. When it's ready I'll post a direct download link here. Could you then:

    1. confirm the Wi‑Fi name of your toy (FLOW-UFO-… or something else) and the model;
    2. connect your phone to the toy's Wi‑Fi, install the test APK and enter the address shown in the release notes;
    3. if there is no picture, send us http://<phone IP>:8085/stats.json and http://<phone IP>:8085/log from a browser on the same network, or long-press → screenshot, so we can see what the toy sends.
  2. compot-dev commented on Oct 15, 2026

    @compot-dev
    Collaborator

    @CatRovacer a test build is ready:

    Direct APK link: https://github.com/OpenIPC/decoder/releases/download/flowufo-187-test1/decoder-flowufo-test1.apk
    Release notes with the steps: https://github.com/OpenIPC/decoder/releases/tag/flowufo-187-test1 · code: #188

    Short version:

    1. Install the APK, connect the phone to the toy's FLOW-UFO-… Wi‑Fi, and stay connected even if Android warns that there is no internet.
    2. Set a slot to flowufo://192.168.169.1:8800 (or just flowufo://).
    3. The app sends the toy's handshake and then shows the video. It's video only, no flight commands are sent.

    This is built from a description of the protocol, not from a real toy, so it may not work on the first try. If there's no picture, or it looks wrong, please wait about 30 s, then open http://127.0.0.1:8085/stats.json and http://127.0.0.1:8085/log in a browser on the same phone and paste both here. Please also tell us the phone model, the Android version, and the toy's Wi‑Fi name and model. Thank you!

  3. CatRovacer commented on Oct 15, 2026

    @CatRovacer
    Author

    First toy: K200
    AccPoint FLY-UFO-1c8414, IP:192.168.1.100
    No image, stats.json:
    {
    "app": "OpenIPC Decoder",
    "version": "2.10",
    "git": "8aaf666",
    "time": "2026-10-15 20:05:05",
    "uptime_s": 374709,
    "device": "OPPO CPH2725 · QTI SM6115 · board bengal",
    "android": "15 (SDK 35)",
    "screen": "1604x720",
    "addresses": [
    "http://192.168.1.100:8085/",
    "http://33.91.55.135:8085/",
    "http://33.95.96.154:8085/"
    ],
    "server": "listening",
    "decoders": [
    {
    "name": "c2.qti.avc.decoder",
    "type": "video/avc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 16,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.avc",
    "type": "video/avc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 16,
    "fps_1080p": 60
    },
    {
    "name": "c2.qti.avc.decoder.low_latency",
    "type": "video/avc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 16,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.avc.low_latency",
    "type": "video/avc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 16,
    "fps_1080p": 60
    },
    {
    "name": "c2.qti.avc.decoder.secure",
    "type": "video/avc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 3,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.avc.secure",
    "type": "video/avc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 3,
    "fps_1080p": 60
    },
    {
    "name": "c2.qti.hevc.decoder",
    "type": "video/hevc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 16,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.hevc",
    "type": "video/hevc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 16,
    "fps_1080p": 60
    },
    {
    "name": "c2.qti.hevc.decoder.low_latency",
    "type": "video/hevc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 16,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.hevc.low_latency",
    "type": "video/hevc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 16,
    "fps_1080p": 60
    },
    {
    "name": "c2.qti.hevc.decoder.secure",
    "type": "video/hevc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 3,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.hevc.secure",
    "type": "video/hevc",
    "hardware": true,
    "adaptive": true,
    "max_instances": 3,
    "fps_1080p": 60
    },
    {
    "name": "c2.qti.vp9.decoder",
    "type": "video/x-vnd.on2.vp9",
    "hardware": true,
    "adaptive": true,
    "max_instances": 6,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.vp9",
    "type": "video/x-vnd.on2.vp9",
    "hardware": true,
    "adaptive": true,
    "max_instances": 6,
    "fps_1080p": 60
    },
    {
    "name": "c2.qti.vp9.decoder.low_latency",
    "type": "video/x-vnd.on2.vp9",
    "hardware": true,
    "adaptive": true,
    "max_instances": 6,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.vp9.low_latency",
    "type": "video/x-vnd.on2.vp9",
    "hardware": true,
    "adaptive": true,
    "max_instances": 6,
    "fps_1080p": 60
    },
    {
    "name": "c2.qti.vp9.decoder.secure",
    "type": "video/x-vnd.on2.vp9",
    "hardware": true,
    "adaptive": true,
    "max_instances": 3,
    "fps_1080p": 60
    },
    {
    "name": "OMX.qcom.video.decoder.vp9.secure",
    "type": "video/x-vnd.on2.vp9",
    "hardware": true,
    "adaptive": true,
    "max_instances": 3,
    "fps_1080p": 60
    },
    {
    "name": "c2.android.av1-dav1d.decoder",
    "type": "video/av01",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "c2.android.avc.decoder",
    "type": "video/avc",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32,
    "fps_1080p": 60
    },
    {
    "name": "OMX.google.h264.decoder",
    "type": "video/avc",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32,
    "fps_1080p": 60
    },
    {
    "name": "c2.android.h263.decoder",
    "type": "video/3gpp",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "OMX.google.h263.decoder",
    "type": "video/3gpp",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "c2.android.hevc.decoder",
    "type": "video/hevc",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "OMX.google.hevc.decoder",
    "type": "video/hevc",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "c2.android.mpeg4.decoder",
    "type": "video/mp4v-es",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "OMX.google.mpeg4.decoder",
    "type": "video/mp4v-es",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "c2.android.vp8.decoder",
    "type": "video/x-vnd.on2.vp8",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32,
    "fps_1080p": 123
    },
    {
    "name": "OMX.google.vp8.decoder",
    "type": "video/x-vnd.on2.vp8",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32,
    "fps_1080p": 123
    },
    {
    "name": "c2.android.vp9.decoder",
    "type": "video/x-vnd.on2.vp9",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "OMX.google.vp9.decoder",
    "type": "video/x-vnd.on2.vp9",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    },
    {
    "name": "c2.android.av1.decoder",
    "type": "video/av01",
    "hardware": false,
    "adaptive": true,
    "max_instances": 32
    }
    ],
    "ui_thread": "ok",
    "mode": "paused",
    "active_slot": 5,
    "single": {
    "url": "flowufo://192.168.1.100:8800",
    "transport": "AUTO",
    "transport_mode": "AUTO",
    "video": false,
    "status": "Waiting for the toy: probing 192.168.1.100:8800",
    "codec": "MJPEG",
    "audio": "NONE",
    "out_fps": 0,
    "decode": "full"
    },
    "slots": [
    {
    "slot": 1,
    "on_screen": false,
    "url": "rtsp://@192.168.1.106:554/stream=0",
    "transport": "check over TCP",
    "transport_mode": "AUTO",
    "video": false,
    "text": "Waiting for a stream check",
    "probe": {
    "state": "waiting"
    }
    },
    {
    "slot": 2,
    "on_screen": false,
    "url": "rtsp://
    @192.168.1.106/stream=2",
    "transport": "check over TCP",
    "transport_mode": "AUTO",
    "video": false,
    "text": "Waiting for a stream check",
    "probe": {
    "state": "waiting"
    }
    },
    {
    "slot": 3,
    "on_screen": false,
    "url": "rtsp://***@192.168.1.237:554/stream=0",
    "transport": "check over TCP",
    "transport_mode": "AUTO",
    "video": false,
    "text": "Waiting for a stream check",
    "probe": {
    "state": "waiting"
    }
    },
    {
    "slot": 4,
    "on_screen": false,
    "url": "udp://192.168.1.101:8800",
    "transport": "UDP listen",
    "transport_mode": "AUTO",
    "video": false,
    "text": "UDP listen slot: not checked in single view",
    "probe": {
    "state": "not checked"
    }
    },
    {
    "slot": 5,
    "on_screen": true,
    "url": "flowufo://192.168.1.100:8800",
    "transport": "AUTO",
    "transport_mode": "AUTO",
    "video": false,
    "text": "Waiting for the toy: probing 192.168.1.100:8800"
    },
    {
    "slot": 6,
    "on_screen": false,
    "url": "flowufo://",
    "transport": "FLOW-UFO UDP",
    "transport_mode": "AUTO",
    "video": false,
    "text": "toy drone slot: not checked in single view",
    "probe": {
    "state": "not checked"
    }
    },
    {
    "slot": 7,
    "on_screen": false,
    "video": false,
    "text": "not configured",
    "probe": {
    "state": "not checked"
    }
    },
    {
    "slot": 8,
    "on_screen": false,
    "video": false,
    "text": "not configured",
    "probe": {
    "state": "not checked"
    }
    },
    {
    "slot": "U",
    "on_screen": false,
    "url": "udp://@:5600",
    "transport": "UDP push",
    "transport_mode": "UDP",
    "video": false,
    "text": "U · not checked in single view",
    "probe": {
    "state": "not checked"
    }
    }
    ]
    }
    2. Model D16, AP: FLOW_251DC0, IP:192.168.169.2
    3. Model : Drone YL3, AP: HF_ba47b828, IP:192.168.80.3
    2,3 no video and image

  4. compot-dev commented on Oct 15, 2026

    @compot-dev
    Collaborator

    Thank you, this helps a lot! A few things we can already see:

    1. K200 (FLY-UFO-1c8414, phone 192.168.1.100): the slot was set to flowufo://192.168.1.100:8800, but that is your phone's own address. The toy itself is almost certainly 192.168.1.1. The 192.168.1.x network suggests an older family of these toys that streams plain RTSP. Could you try these two slots and tell us what each shows?

    • rtsp://192.168.1.1:7070/webcam
    • flowufo://192.168.1.1:8800

    2. D16 (FLOW_251DC0, phone 192.168.169.2): the toy should be 192.168.169.1, so please use flowufo://192.168.169.1:8800. If there's still no picture, please send http://127.0.0.1:8085/stats.json and http://127.0.0.1:8085/log from this toy after about 30 s. The flowufo part of stats.json and the FLOW-UFO lines in the log show whether the toy answers at all. The D16 may use a different protocol (video on another port), and the log will tell us.

    3. YL3 (HF_ba47b828, phone 192.168.80.3): this looks like yet another family. Which app does its manual or box tell you to install (name, or a link to the store page)? The toy is probably 192.168.80.1.

    For each toy, the vendor app's name helps us most, since toys that use the same app usually share a protocol.

  5. compot-dev commented on Oct 15, 2026

    @compot-dev
    Collaborator

    @CatRovacer an update and a short how-to for the next tests.

    What we learned about your three toys

    Toy Wi‑Fi Toy address What it is Status
    K200 FLY-UFO-… 192.168.1.1 KY UFO family: plain RTSP video rtsp://192.168.1.1:7070/webcam, which also expects a small "heartbeat" packet every second next build sends the heartbeat by itself
    D16 FLOW_… 192.168.169.1 the FLOW-UFO protocol from the first test build; a few bytes are being corrected after comparing with turbodrone, where the D16 is known to work next build
    YL3 HF_… 192.168.80.1 a Jieli AC79 camera (vendor app "DVRunning 2"): the app asks for the stream over TCP 3333 and the video comes back over UDP new transport jieli:// in the next build

    The next test build will cover all three. I'll post the direct link here with the exact address for each toy.

    How to send us what the app sees (no extra tools needed: the decoder has a small built-in web server)

    1. Connect the phone to the toy's Wi‑Fi and stay connected even if Android says "no internet". Close the toy's own app, because the toy usually talks to one app at a time.
    2. In the decoder, open the slot for that toy and wait about 30 seconds.
    3. On the same phone, open a browser and go to:
      • http://127.0.0.1:8085/log: the app's own log (last ~500 lines). It shows what the app sent to the toy and what came back.
      • http://127.0.0.1:8085/stats.json: the current state of the slot.
    4. Copy both pages into a comment here, one comment per toy, and say which toy it is. Please do it right after the attempt, since the log keeps only the latest lines.

    A screenshot (long-press on the picture) helps too if a picture appears but looks wrong (colours, stripes). Thanks a lot for testing!

  6. CatRovacer commented on Oct 15, 2026

    @CatRovacer
    Author

    На D16 работает flyufo://192.168.169.1:8800. Ориентации картинки и экрана правильные.

  7. compot-dev commented on Oct 15, 2026

    @compot-dev
    Collaborator

    @CatRovacer great news about the D16, thank you! flowufo://192.168.169.1:8800 works on the very first test build.

    A quick question about the photo of your three drones (the orange one on the YL3 box, the grey one on the D16 box, and the grey one with black guards): which drone is which? Please label them like this:

    • orange: K200 / YL3 / …
    • grey with black guards: …
    • grey on the D16 box: D16 (?)

    For each, please also tell us its Wi‑Fi name (FLY-UFO-…, FLOW_…, HF_…) and the app from its manual (KY UFO, WIFI UAV, DVRunning 2…). We'll put this table in our docs. May we use your photo there too?

    The next test build is coming soon: jieli://192.168.80.1 for the YL3, and the K200 picture turned upright.


    Отличные новости про D16, спасибо! flowufo://192.168.169.1:8800 заработал уже на первой тестовой сборке.

    Короткий вопрос по фото трёх дронов (оранжевый на коробке YL3, серый на коробке D16, серый с чёрными защитами): подпишите, пожалуйста, какой из них какой:

    • оранжевый: K200 / YL3 / …
    • серый с чёрными защитами: …
    • серый на коробке D16: D16 (?)

    И для каждого: имя его Wi‑Fi (FLY-UFO-…, FLOW_…, HF_…) и приложение из инструкции (KY UFO, WIFI UAV, DVRunning 2…). Сведём это в таблицу в документации. Можно ли использовать там ваше фото?

    Следующая тестовая сборка уже скоро: jieli://192.168.80.1 для YL3 и картинка K200, повёрнутая как надо.

  8. compot-dev commented on Oct 15, 2026

    @compot-dev
    Collaborator

    @CatRovacer test build 2 is ready. It replaces test build 1.

    Direct APK link: https://github.com/OpenIPC/decoder/releases/download/toys-187-test2/decoder-toys-test2.apk
    (release notes: https://github.com/OpenIPC/decoder/releases/tag/toys-187-test2)

    Toy Slot address What to check
    D16 flowufo://192.168.169.1:8800 still works as before
    K200 rtsp://192.168.1.1:7070/webcam the picture should now be upright and fill the screen (turned 90° counter-clockwise by the app). If it turns the wrong way, try rtsp://192.168.1.1:7070/webcam?rotate=270
    YL3 jieli://192.168.80.1 new: is there any picture?

    Logs: they stay in the app while it runs, even after you leave the toy's Wi‑Fi. Join a Wi‑Fi with internet, open http://127.0.0.1:8085/log and http://127.0.0.1:8085/stats.json in the phone's browser, save each page as a file (Share → Save, or Download) and attach the files to a comment (drag them in, GitHub accepts .txt files). The log is much cleaner now. A "Save report" button that writes both into one file is coming in a later build.


    @CatRovacer готова тестовая сборка 2, она заменяет первую.

    Прямая ссылка на APK: https://github.com/OpenIPC/decoder/releases/download/toys-187-test2/decoder-toys-test2.apk
    (описание: https://github.com/OpenIPC/decoder/releases/tag/toys-187-test2)

    Дрон Адрес слота Что проверить
    D16 flowufo://192.168.169.1:8800 работает, как раньше
    K200 rtsp://192.168.1.1:7070/webcam картинка теперь должна стоять ровно и занимать экран (приложение поворачивает её на 90° против часовой). Если повернулась не туда, попробуйте rtsp://192.168.1.1:7070/webcam?rotate=270
    YL3 jieli://192.168.80.1 новое: есть ли картинка?

    Логи: они хранятся в приложении, пока оно открыто, даже после отключения от Wi‑Fi дрона. Подключитесь к Wi‑Fi с интернетом, откройте в браузере телефона http://127.0.0.1:8085/log и http://127.0.0.1:8085/stats.json, сохраните каждую страницу файлом (Поделиться → Сохранить или Скачать) и приложите файлы к комментарию (перетащите, GitHub принимает .txt). Лог теперь гораздо чище. Кнопка «Save report», которая сохраняет всё одним файлом, будет в следующей сборке.

  9. CatRovacer commented on Oct 16, 2026

    @CatRovacer
    Author

    K200 картинка почти правильная, но повернулась "не в ту дверь". С параметром ?rotate=270 орииентация правильная, но появилась дикая задержка, примерно 1сек.
    YL3: картинки нет, логи прикрепил.
    На фото K200 справа внизу, крупнее, с черной решеткой защитой виртов сверху.
    Кнопку сохранить на странице decoder не нашел, сохраняял из контестного меню. Наверно невнимательно смотрел.

    log.txt

    stats.json.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions