main fixes
This commit is contained in:
132
VIDEO_STREAMING_FIX.md
Normal file
132
VIDEO_STREAMING_FIX.md
Normal 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.
|
||||
|
||||
Reference in New Issue
Block a user