Files
cam_control_android/VIDEO_STREAMING_FIX.md
2025-12-09 21:21:26 +09:00

133 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Исправление: Отправка видео на сервер
## Проблема
Приложение показывало превью камеры локально, но **видео вообще не отправлялось на сервер**.
### Анализ логов
Из `logcat` было видно:
- ✓ WebSocket подключился успешно: `Connected! Response code=101`
- ✓ Сервер ответил: `Message received: {"error": "Invalid room or password"}`
-Но фреймы не отправлялись: в логах нет сообщений о `sendBinary`
- ❌ Функция `StreamViewModel.sendVideoFrame()` вообще не вызывалась
## Корень проблемы
### 1. CameraManager не обрабатывал фреймы
Файл `CameraManager.kt` только показывал превью, но не захватывал видео фреймы.
- Использовался только `Preview` use case для отображения
- Отсутствовал `ImageAnalysis` use case для захвата фреймов
### 2. Нет связи между камерой и ViewModel
`MainActivity.kt` запускал камеру, но не передавал фреймы в `ViewModel`:
```kotlin
// ДО: просто стартует камеру без callback
cameraManager.startCamera(lifecycleOwner, pv.surfaceProvider, onError)
// НУЖНО: передать фреймы в ViewModel
cameraManager.startCamera(lifecycleOwner, pv.surfaceProvider, onError,
onFrame = { frameData -> viewModel.sendVideoFrame(frameData) }
)
```
### 3. Проблемы с отправкой бинарных данных
`WebSocketManager.sendBinary()` использовал рефлексию вместо стандартного API:
```kotlin
// ДО: сложная рефлексия
val byteStringClass = Class.forName("okhttp3.ByteString")
val ofMethod = byteStringClass.getMethod("of", ByteArray::class.java)
// ... и так далее
// ПОСЛЕ: простой и надёжный API
val byteString = ByteString.of(*data)
webSocket?.send(byteString)
```
## Решение
### 1. ✅ Обновлен CameraManager
Добавлен `ImageAnalysis` для захвата видео фреймов:
```kotlin
val imageAnalysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
.build()
.apply {
setAnalyzer(analysisExecutor) { imageProxy ->
processFrame(imageProxy)
}
}
// Добавлена обработка фреймов
private fun processFrame(imageProxy: ImageProxy) {
// Преобразование в ByteArray
val frameData = ByteArray(buffer.remaining())
buffer.get(frameData)
// Отправка через callback
onFrameAvailable?.invoke(frameData)
}
```
### 2. ✅ Обновлена MainActivity
Добавлен callback для передачи фреймов:
```kotlin
cameraManager.startCamera(
lifecycleOwner,
pv.surfaceProvider,
onError = { err -> Log.e("CameraManager", "Camera error: $err") },
onFrame = { frameData ->
viewModel.sendVideoFrame(frameData)
}
)
```
### 3. ✅ Исправлен WebSocketManager
Заменена рефлексия на стандартный API:
```kotlin
import okhttp3.ByteString
fun sendBinary(data: ByteArray) {
try {
val byteString = ByteString.of(*data)
webSocket?.send(byteString)
Log.d("WebSocket", "Binary data sent: ${data.size} bytes")
} catch (e: Exception) {
Log.e("WebSocket", "Binary send error: ${e.message}")
onError(e.message ?: "Failed to send binary data")
}
}
```
### 4. ✅ Улучшено логирование
Добавлены логи для отслеживания передачи:
- `CameraManager`: "Processing X frames/5s, sending to server"
- `StreamViewModel`: "FPS: X, Total bytes sent: Y"
- `WebSocket`: "Binary data sent: X bytes"
## Проверка
После исправления в логах должны появиться:
1. При подключении:
```
WebSocket: Connected! Response code=101
CameraManager: Camera started successfully with video streaming
StreamViewModel: Connected to server
```
2. При потоке видео:
```
CameraManager: Processing 25 frames/5s, sending to server
WebSocket: Binary data sent: 12345 bytes
StreamViewModel: FPS: 25, Total bytes sent: 308640
```
## Файлы изменены
- ✅ `CameraManager.kt` - Добавлен ImageAnalysis и обработка фреймов
- ✅ `MainActivity.kt` - Добавлена передача фреймов в ViewModel
- ✅ `WebSocketManager.kt` - Исправлена отправка бинарных данных
- ✅ `StreamViewModel.kt` - Улучшено логирование
## Результат
Теперь видео из камеры будет **отправляться на сервер** сразу после успешного подключения WebSocket.