main fixes

This commit is contained in:
2025-12-09 21:21:26 +09:00
parent 752b2fb1ca
commit 568ca73a11
33 changed files with 4353 additions and 345 deletions

132
VIDEO_STREAMING_FIX.md Normal file
View File

@@ -0,0 +1,132 @@
# Исправление: Отправка видео на сервер
## Проблема
Приложение показывало превью камеры локально, но **видео вообще не отправлялось на сервер**.
### Анализ логов
Из `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.