Разработка мобильного приложения для видеонаблюдения (IP-камеры)
IP-камеры транслируют видео по нескольким протоколам: RTSP — стандарт де-факто для локальных сетей, HLS/DASH — для облачных решений, WebRTC — если нужна минимальная задержка (< 500 мс). Мобильное приложение для видеонаблюдения начинается с выбора протокола под конкретную задачу, и это решение определяет всю архитектуру.
RTSP: декодирование видео на мобильном
RTSP-поток с камеры — это H.264/H.265 видео, завёрнутое в RTP-пакеты. Нативного RTSP-плеера ни в iOS, ни в Android нет. Варианты:
Android: ExoPlayer с расширением extension-rtsp (начиная с Media3 1.0). До этого — только VLC for Android SDK (libvlc-android). ExoPlayer Media3 с RTSP работает корректно для большинства камер на H.264, но на H.265 с некоторыми RTSP-серверами даёт SOURCE_ERROR из-за нестандартных SDP-атрибутов.
class CameraPlayerManager(private val context: Context) {
private var player: ExoPlayer? = null
fun startStream(rtspUrl: String, surfaceView: SurfaceView) {
val mediaItem = MediaItem.Builder()
.setUri(Uri.parse(rtspUrl))
.build()
player = ExoPlayer.Builder(context)
.setMediaSourceFactory(
DefaultMediaSourceFactory(context)
.setLiveTargetOffsetMs(500)
)
.build()
.also { exo ->
exo.setVideoSurfaceView(surfaceView)
exo.setMediaItem(mediaItem)
exo.prepare()
exo.play()
}
}
fun release() {
player?.release()
player = null
}
}
iOS: AVPlayer не поддерживает RTSP. Пути: VLCKit (работает, но бинарник ~20 МБ), FFmpegKit с нативной компиляцией FFmpeg (тяжелее, но максимально гибко), либо собственный RTSP-клиент на RTP/UDP через Network.framework. Последний вариант трудоёмкий, но даёт полный контроль над буферизацией и задержкой.
ONVIF: обнаружение камер в сети
ONVIF — стандарт для IP-камер (Hikvision, Dahua, Axis, Reolink). Профиль S определяет GetStreamUri, GetSnapshotUri, PTZ-управление. WS-Discovery для обнаружения устройств в локальной сети.
// Android: WS-Discovery multicast
class ONVIFDiscovery {
private val MULTICAST_ADDRESS = "239.255.255.250"
private val MULTICAST_PORT = 3702
suspend fun discoverDevices(timeout: Long = 3000): List<ONVIFDevice> {
val socket = MulticastSocket(MULTICAST_PORT)
socket.joinGroup(InetAddress.getByName(MULTICAST_ADDRESS))
socket.soTimeout = timeout.toInt()
val probeMessage = buildWSDiscoveryProbe()
val packet = DatagramPacket(
probeMessage.toByteArray(),
probeMessage.length,
InetAddress.getByName(MULTICAST_ADDRESS),
MULTICAST_PORT
)
socket.send(packet)
val devices = mutableListOf<ONVIFDevice>()
val buffer = ByteArray(4096)
try {
while (true) {
val response = DatagramPacket(buffer, buffer.size)
socket.receive(response)
parseWSDiscoveryResponse(String(response.data, 0, response.length))
?.let { devices.add(it) }
}
} catch (e: SocketTimeoutException) { /* нормальное завершение */ }
socket.close()
return devices
}
}
Для получения RTSP URL: SOAP-запрос GetStreamUri с авторизацией WS-Security (Digest auth). Библиотека onvif4java упрощает, но часто отстаёт от актуальных прошивок камер — проще написать SOAP-клиент на Retrofit с кастомным конвертером.
Многокамерный просмотр
Сетка из 4 или 9 камер одновременно — тяжёлая задача. Каждый RTSP-поток требует отдельного декодера. На Android с 9 камерами Full HD рискуем исчерпать аппаратные декодеры (их обычно 4-8 на чипе); остальные уходят на программный декодер с просадкой FPS до 5-10 кадров.
Решение: для сетки используем MJPEG-снапшоты через ONVIF GetSnapshotUri с обновлением раз в 2-3 секунды вместо полного видеопотока. Полный RTSP включаем только при тапе на камеру — режим полного экрана. Это компромисс между нагрузкой и информативностью.
Запись и история: локальное и облачное хранение
Запись клипов с камеры на телефон: скачиваем через ONVIF GetRecordings или ISAPI (Hikvision). Локально сохраняем в MediaStore (Android 10+) или Photos Library (iOS). Для облачных камер — прямые ссылки на MP4 из облака производителя.
Motion detection: либо аппаратный (в самой камере, события приходят через ONVIF Event Service), либо программный на мобильном через сравнение кадров по YUV разнице между предыдущим и текущим. Аппаратный надёжнее — меньше ложных срабатываний.
Разработка мобильного приложения с RTSP-просмотром одной камеры и базовым ONVIF-управлением: 4-5 недель. Многокамерная система с WS-Discovery, PTZ-управлением, историей записей и пуш-алертами по motion: 8-12 недель. Стоимость рассчитывается индивидуально после анализа модельного ряда камер и требований к хранению.







