Browse Source

Add Android live stream audio switch and document radio behavior

master
evgeny 4 days ago
parent
commit
7e7d86e4d3
  1. 19
      doc/stream.txt
  2. 7
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt

19
doc/stream.txt

@ -416,12 +416,12 @@ adm_tags — блок владельца, для самоуправляемых
Отдельного STREAM_ANNOUNCE, broadcast-обновлений и собственных TTL/версий анонсов нет. Отдельного STREAM_ANNOUNCE, broadcast-обновлений и собственных TTL/версий анонсов нет.
Опции содержат: Опции содержат:
- stream_source: активна ли собственная трансляция; если активна — её source_epoch и параметры FEC. - stream_source: активна ли собственная трансляция; если активна — её source_epoch, параметры FEC и включён ли звук.
- stream_subscriptions: список (source_node_id, source_epoch), на которые узел локально подписан. - stream_subscriptions: список (source_node_id, source_epoch), на которые узел локально подписан.
Формат — совместимые с существующим плоским userinfo строковые значения; список кодируется однозначно, Формат — совместимые с существующим плоским userinfo строковые значения; список кодируется однозначно,
со строгим разбором 64-битных IDs без потери точности через JSON numbers. со строгим разбором 64-битных IDs без потери точности через JSON numbers.
Зафиксированный формат: Зафиксированный формат:
stream_source = "<source_epoch:16 lowercase hex>:<n:decimal>:<r:decimal>:<block_size:decimal>" stream_source = "<source_epoch:16 lowercase hex>:<n:decimal>:<r:decimal>:<block_size:decimal>:<audio:0|1>"
stream_subscriptions = "<source_node_id:16 lowercase hex>:<source_epoch:16 lowercase hex>[:r],..." stream_subscriptions = "<source_node_id:16 lowercase hex>:<source_epoch:16 lowercase hex>[:r],..."
Суффикс :r означает внутренний приём только ради помощи, без локального зрителя. Суффикс :r означает внутренний приём только ради помощи, без локального зрителя.
Локальный viewer на общем экземпляре снимает :r; закрытие последнего viewer возвращает :r, если помощь ещё используется. Локальный viewer на общем экземпляре снимает :r; закрытие последнего viewer возвращает :r, если помощь ещё используется.
@ -925,6 +925,21 @@ Android:
завершается с диагностикой, приём рации сохраняется. Окно VAD/экран/разрешения не обходятся общим захватом. завершается с диагностикой, приём рации сохраняется. Окно VAD/экран/разрешения не обходятся общим захватом.
Звонок и voice recording по-прежнему исключают публикацию в обе стороны. Звонок и voice recording по-прежнему исключают публикацию в обе стороны.
Звук трансляции и рация (Android и desktop):
- Во время публикации с микрофоном звук можно выключить и включить. Заглушается только копия PCM
трансляции перед кодированием; захват, формат аудиотрека, PTS и source_epoch не меняются.
Opus продолжает передавать тишину, рация получает исходный PCM. Для публикации без аудиотрека
включение микрофона требует нового запуска, как и раньше.
- audio в подписанном stream_source означает положение переключателя источника, а не наличие речи.
У локального viewer рация этого источника в том же канале не воспроизводится, пока audio=1.
Громкость зрителя, паузы речи, отдельный микрофон рации и буферизация правило не меняют.
- Raw readers и relay без media cursor рацию не подавляют. Последний закрытый viewer,
выключение звука источником, завершение публикации, новая эпоха и остановка сервиса снимают подавление.
Ручное отключение участника независимо сохраняется в БД; итог — ручное ИЛИ временное отключение.
Подписка рации, пересылка, индикация говорящего и занятость эфира продолжают работать.
- Изменение состояния не синхронизирует задержанные буферы рации и трансляции. Управление звуком
не запускает повторный захват, пересогласование видео или сброс шкалы воспроизведения.
Логи: stream — epoch/owners, очереди, GAP и teardown; video — codec/config, KEY, PTS и декодер. Логи: stream — epoch/owners, очереди, GAP и teardown; video — codec/config, KEY, PTS и декодер.
Kotlin progress — DEBUG раз в секунду; C packet-level диагностика — TRACE по запросу. Kotlin progress — DEBUG раз в секунду; C packet-level диагностика — TRACE по запросу.
Проверки: test_stream_media (все пары потерь 6+2, parser/границы/GAP), test_android_stream Проверки: test_stream_media (все пары потерь 6+2, parser/границы/GAP), test_android_stream

7
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/StreamScreen.kt

@ -123,6 +123,13 @@ fun StreamScreen(channelId: String, channelName: String, sources: List<StreamSou
}) { padding -> }) { padding ->
Column(Modifier.fillMaxSize().padding(padding).padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { Column(Modifier.fillMaxSize().padding(padding).padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
Text(channelName, style = MaterialTheme.typography.titleMedium) Text(channelName, style = MaterialTheme.typography.titleMedium)
if (local?.ongoing == true && (selected == null || selected.self)) {
Row {
Checkbox(checked = local.audioEnabled, onCheckedChange = StreamController::setAudioEnabled,
enabled = local.phase == StreamPhase.LIVE && local.audioAvailable)
Text(stringResource(R.string.stream_audio), Modifier.padding(top = 12.dp))
}
}
if (selected != null) { if (selected != null) {
Text(selected.displayName, style = MaterialTheme.typography.titleSmall) Text(selected.displayName, style = MaterialTheme.typography.titleSmall)
if (selected.self && local?.ongoing == true) { if (selected.self && local?.ongoing == true) {

Loading…
Cancel
Save