Потрібна допомога у вирішенні “Android video widget failed to display RTSP video streams”

Усі статті, обговорення, новини про Mobile — в одному місці. Підписуйтеся на телеграм-канал!

(це для ЗС* !!)

Доброго дня шановні колеги,

Потрібна допомога експертів по Android, хто стикався з video stream під ним або ж може розібратись в цій проблемі. Короткий опис нижче. Це з цієї issue. Це блокуючий дефект для функціоналу для одного виробу для організації котра нас всіх захищає🙂. Будемо дуже вдячні за допомогу з вирішенням цієї проблеми. Обговорення в коментарях нижче або ж на github.

Python: 3.9 OS: Android 5 and Android 9, arm v7a and v8a Kivy: 2.1 Kivy installation method: both buildozer and p4a, using both docker and virtualbox

Video widget for rtsp streams does not play. It shows blank (white screen). After Video.source set to ’rtsp://’ no video but blank widget show. * Some side effects also possible like hang Video widget process, futher functions of this video vidget is blocked, next .source changes has no effect, application is unable to exit etc.

Code (minimal):

import kivy
from kivy.uix.video import Video
from kivy.app import App

class TestApp(App):
    def build(self):
        return Video(state='play',
            source='rtsp://wowzaec2demo.streamlock.net:554/vod/mp4:BigBuckBunny_115k.mp4',
    )
TestApp().run()

I tried many different rtsp sources, including internet and local cctv cams, but all without success

Code

import kivy
from kivy.uix.video import Video
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.app import App
from kivy.metrics import sp

SOURCES = {
    'logo': 'https://kivy.org/static/images/logo_kivy_white.png',
    'intr': 'https://kivy.org/doc/stable/_images/gs-introduction.png',
    'https': 'https://www.wowza.com/wp-content/uploads/home-video-flowplayer-1120x630-1.mp4',
    'RTSP': 'rtsp://wowzaec2demo.streamlock.net:554/vod/mp4:BigBuckBunny_115k.mp4',
    '29.50': 'rtsp://192.168.29.50:554/onvif1',
    '95-h264': 'rtsp://192.168.88.95:554/av0_0',
    '95-mjpg': 'rtsp://192.168.88.95:554/av0_1',
    '96-lores': 'rtsp://192.168.88.96:554/av0_3',
}

class TestApp(App):
    def build(self):
        root = BoxLayout(orientation='vertical')
        video = Video(state = 'play', source = SOURCES['logo'])
        root.add_widget(video)
        btns = BoxLayout(height=sp(32), size_hint=(1,None))
        root.add_widget(btns)
        for k,v in SOURCES.items():
            def btn_fn(i, s=v):
                video.source = s
                video.state = 'play'
            btns.add_widget(Button(text=k, on_release=btn_fn))
        return root

TestApp().run()

Dockerfile

FROM p4a
ENV ANDROIDSDK="$ANDROID_HOME/android-sdk" \
    ANDROIDNDK="$ANDROID_HOME/android-ndk" \
    ANDROIDAPI="27" \
    NDKAPI="21"
WORKDIR /home/user/test
ENTRYPOINT . /home/user/app/venv/bin/activate && p4a apk --private .

.p4a

--package=org.test.test
--name "Video test"
--version 0.1
--dist-name test
--permission INTERNET
--bootstrap=sdl2
--orientation landscape
--arch=armeabi-v7a
--requirements=hostpython3,python3,kivy,ffmpeg,ffpyplayer,ffpyplayer_codecs

buildozer.spec

[app]
title = Video test
package.name = test
package.domain = org.test
source.dir = .
version = 0.1
requirements = hostpython3,python3,kivy,ffmpeg,ffpyplayer,ffpyplayer_codecs
android.permissions = INTERNET
android.arch = armeabi-v7a
[buildozer]
build_dir = /var/tmp/buildozer.test
bin_dir = ./dist

how to build test apk

git clone https://github.com/kivy/python-for-android
docker build -t p4a python-for-android/
docker build -t p4a_test .
docker run -it --name test-builder -v <PWD_PATH>:/home/user/test p4a_test
adb install -r test-debug-0.1.apk
adb shell am start -n org.test.test/org.kivy.android.PythonActivity
adb logcat python:v *:e

how to reproduce

after starting, the android application will show the first source — kivy logo image. You may switch in to another kivy image using the second button on the screen bottom. And to https video source. And back to logo. It works. But when your switch to rtsp stream, video is not displayed.

👍ПодобаєтьсяСподобалось2
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

1. Wireshark логи в студію.
2. Це RTSP тут можуть бути нюанси за NAT’ом. Раджу створити RTSP стрім в локальній мережі і перевірити чи воно все ще не працює. Ставлю 100 грн на ЗСУ, що воно працюватииме в локальній мережі нормально. А далі це справа конфігурації мережі і коректно ініціалізації RTSP протоколу (методи OPTIONS, DESCRIBE, PLAY) (звісно якщо для вас актуальна взаємодія через NAT).

Дякую. Але поки не маю можливості зняти вайршарк логи трафіку між андроід гаджетом і cctv камерою наприклад. Але NAT тут напевно ні до чого бо зв’язок напряму в межах одного LAN. Контрольний VLC-плеєр на тому ж гаджеті відтворює всі тестові rtsp джерела.

І от те во?

rtsp:/...​mp4:BigBuckBunny_115k.mp4

Я на всяк випадку на своєму VLC перевірив, у мене не працює)

Логи же в будь-якому випадку знадобляться в майбутньому у мене таке передчуття. Можна запустити вашу аплікуху в емульованому андроід пристрої на компі і зробити capture на мережевому інтерфейсі хоста, де адроід пристрій емулюється.

Те во vlc не грає — в мене теж не грає коли я в корпоративній мережі за файрволом. З білих мереж грає. Маю скріншот :)

Насправді то не дивно. Сам RTSP відео не транспортує, він тільки «домовляється про його передачу» через певні UDP сокети. Саме тому через файрволи воно і не працює. Я глянув URL в екзамплі і подумав що це і причина.

Не завжди через UDP, є режим, коли все ходить через один TCP порт: і команди, і медіа.

параметри задаються в SDP,
я так не зрозумів, знайшли причину, не підтримується кодек, чи не можуть пробити NAT?

параметри задаються в SDP

В цьому випадку на стороні програвача цим керує ffmpeg, йому б можна було б передати цю опцію, але хз чи можливо це зробити в kivi. Ще я бачив коли на самій камері це конфігурується, і тоді це може бути параметр в url’і до стріма.

я так не зрозумів, знайшли причину

Мабуть, не знайшли.
Навряд саме кодек, можливо, чогось не вистачає для демуксера/протокола rtsp. Це можна було б перевірити самою програмою ffmpeg, просто треба опцію для її збірки в докері додати, але я хз як потім цей бінарь з лібами закинути на андроід і запустити.
Більш вірогідно, що в цьому kivi якось криво використовується ffmpeg. Я подивився на код, там обгортка над обгорткою, в пітоні не шарю, не розібрався.

Я так розумію, це для IP камер застосунок? Врахуйте тоді, що стандартний SDK не вміє в digest авторизацію, а тому, якщо камери запаролені, то навіть пофіксивши проблему в цьому пайтоностькому врапері для тестових лінків з зайчиком, в «бойових» умовах працювати не буде. Взагалі працювати з відеострімами і без кроссплафроми боляче, і іноді вимагає форкання ліб на NDK рівні

Там в issue ссылка на фикс этой проблемы в репо github.com/...​r-android/pull/2644/files
Этот фикс попал в вашу сборку? Фикс в ветку develop, а вы клонируете без указания ветки, возможно там по дефолту master

Thank you for your participation. But this is not a fix. Just the inclusion of the rtsp transport and few codecs in the basic ffpyplayer config. Without this “support”, they are only enabled if ffpyplayer_codecs is included in dependencies. In the example above, ffpyplayer_codecs is included in dependencies, so this fix is ​​not needed and will not have any effect.

Сорри, я не понял ваш ответ. Этот фикс добавляет поддержку нужных вам сетевых протоколов и демуксера rtsp, а именно это патч скрипта сборки либы ffmpeg, без которого либа не проиграет этот формат. А при чем ffpyplayer_codecs? Я смотрю, что эта штука просто добавляет зависимости энкодеров.
Upd: увидел теперь, что ffpyplayer_codecs включает другую ветку условия. Ну тогда остается актуальным совет проверить сборку ffmpeg’а:
Кстати, если убрать вот эту строчку
github.com/...​es/ffmpeg/__init__.py#L96
то вместе с либой должны собраться бинари, и тогда утилитой ffmpeg можно будет проверить сборку либы: ffmpeg —list-demuxers
В выводе должен быть rtsp

ok. Short answer: Yes, this fix was in our build. This is in p4a master since 2022.09.05. And that does not solve the problem.

About —list-demuxers. Sorry, i dont know how to do this. Python for android is dedicated to build single apk file that run specific main.py script of my application. So, if you know simple way to start ffmpeg —list-demuxers on android device from p4a builded apk please let me know. Thanks

Ок, я понял, тогда давайте попробуем с более простого варианта.
Вам точно нужны энкодеры в приложении? Вот этот ffpyplayer_codecs включает 3 энкодера. И из-за него сборка ffmpeg идет по вот той странной ветке if. Если вам не нужно ничего кодировать в приложении, то можно отключить ffpyplayer_codecs, тогда сборка ffmpeg’а пойдет по нормальной ветке, в которую собственно и был добавлен фикс для поддержки rtsp.
Если все-таки нужны энкодеры, то попробуйте вот это

# Enable all codecs:
flags += [
’—enable-parsers’,
’—enable-decoders’,
’—enable-encoders’,
’—enable-muxers’,
’—enable-demuxers’,
]

заменить на это

# Enable codecs only for .mp4:
flags += [
’—enable-parser=aac,ac3,h261,h264,mpegaudio,mpeg4video,mpegvideo,vc1′,
’—enable-decoder=aac,h264,mpeg4,mpegvideo’,
’—enable-muxer=h264,mov,mp4,mpeg2video’,
’—enable-demuxer=aac,h264,m4v,mov,mpegvideo,vc1,rtsp’,
]

Пересобрать всё и попробовать заработает ли rtsp

I am 99 percent sure that I tried to build apk without ffmpeg_codecs dependency but with ’rtsp fixed’ ffmpeg recepie. With no luck. But i’ll try once more asap

Еще можно попробовать добавить к строке —enable-protocol=... протокол rtp

Сборка ffmpeg там выглядит странно. Ставлю на то, что все-таки в ней нет поддержки rtsp. Почему:
www.ffmpeg.org/...​peg-formats.html#Demuxers
Написано «When you configure your FFmpeg build, all the supported demuxers are enabled by default.» Но в скрипте сборки у них сразу ставится флаг ’—disable-everything’: github.com/...​es/ffmpeg/__init__.py#L30
Это значит, что «and selectively enable a single demuxer with the option —enable-demuxer=DEMUXER», то есть для каждого формата нужно отдельно включать флаг. В скрипте этого нет, зато есть ’—enable-demuxers’ - что это вообще такое, откуда оно? Такого флага нет в ffmpeg’е: github.com/...​lob/release/4.3/configure Также как и наверное всех прочих под комментом «# Enable all codecs:»

В скрипте этого нет, зато есть ’—enable-demuxers’ - что это вообще такое, откуда оно? Такого флага нет в ffmpeg’е: github.com/...​lob/release/4.3/configure Также как и наверное всех прочих под комментом «# Enable all codecs:»

Я не прав, разобрался, все эти ’—enable-demuxers’ и прочие подобные флаги в configure не находятся, потому что они там динамически обрабатываются, типа —enable-*

Якщо є можливiсть не використовувати цей kivi, то перейдiть на java/kotlin. Виглядає так, наче воно не пiдтримує rtsp. Як варiант — передавати uri у нативний плеєр чи vlc та грати там, якщо цей кейс Вам буде зручним

колись колупав той ківі, таке враження що воно зламане, може дійсно простіше на kotlin зробити

Что вам надо запилить? Я, может, быстрее вам на котлине это сделаю, чем вы найдете решение

На 8-й місяць війни можна перейти на нормальний технологічний стек. Як на мене вже час робити по-нормальному.

хоча би зробити обгортку ffmpeg libav live555

Якщо ви про HLS та Dash, то вони мають багато оверхеду.

просто щоб припинити офтопік — зараз під ківі написано більше 1 мегабайта сарсів (це епізодично з 14 року) які успішно працюють під лінукс і віндовз і разбері. практично все крім відео працює на андроіді. тому задача «а давайте все нах перепишемо правильно» поки не розглядається.

спочатку потрібно спуститись до рівня мережі та кодеків і зрозуміти, власне вчому проблема.
я так розумію, що хайлевел фреймворк такого не дозволяє.

Підписатись на коментарі