Skip to content

SRT setOnlyVideo(true) Still Sends Audio Track in PSI Tables #2023

@Piyoxz

Description

@Piyoxz

When using setOnlyVideo(true) for SRT streaming, the MPEG-TS muxer still includes audio track information in PSI tables (PAT/PMT).

As a result, downstream servers (e.g. ZLMediaKit) detect and expect an audio track even though no audio packets are actually sent.

Impact

This behavior causes several issues on strict TS demuxers:

  • ❌ Phantom audio track detected (e.g. mpeg4-generic)
  • ❌ Potential TS demuxer crashes when audio packets never arrive
  • ❌ Incorrect stream metadata reported by server APIs

Expected Behavior

When setOnlyVideo(true) is called before startStream():

  • ✅ PSI tables (PAT/PMT) contain only video track
  • ✅ No audio PID registered in PMT
  • ✅ Server receives pure video-only metadata
  • ✅ No audio packets sent (this already works correctly)

Actual Behavior

  • ✅ SrtClient.setOnlyVideo(true) correctly sets commandsManager.audioDisabled = true
  • ✅ SrtSender.getMpegTsPackets() correctly skips audio packets
  • ❌ Audio track is still registered in PSI tables

Root Cause

In SrtSender.kt:

private fun setTrackConfig(videoEnabled: Boolean, audioEnabled: Boolean) {
  Pid.reset()
  service.clearTracks()
  if (audioEnabled) service.addTrack(commandsManager.audioCodec.toCodec()) // ❌ Audio always added
  if (videoEnabled) service.addTrack(commandsManager.videoCodec.toCodec())
  service.generatePmt()
  psiManager.updateService(service)
}
  • audioEnabled is derived from !commandsManager.audioDisabled
  • However, this method does not respect setOnlyVideo(true)
  • As a result, audio track metadata is added even when audio is explicitly disabled

Server Detection Example (ZLMediaKit)
/index/api/getMediaList response:

{
  "tracks": [
    {
      "codec_id": 2,
      "codec_id_name": "mpeg4-generic", // ❌ Phantom audio track
      "codec_type": 1,
      "channels": 1,
      "sample_rate": 8000
    },
    {
      "codec_id": 1,
      "codec_id_name": "H265",
      "codec_type": 0,
      "width": 1280,
      "height": 720
    }
  ]
}

Steps to Reproduce

  1. Prepare video encoder (H265) + audio encoder (AAC)
  2. Call srtClient.setOnlyVideo(true)
  3. Start streaming:
    startStream("srt://server:9000?streamid=...")
  4. Query server metadata (e.g. ZLMediaKit API)
  5. Observe: Both audio and video tracks detected

Proposed Fix

Modify SrtSender.setTrackConfig() to respect commandsManager.audioDisabled:

private fun setTrackConfig(videoEnabled: Boolean, audioEnabled: Boolean) {
  Pid.reset()
  service.clearTracks()

  // Only add audio track if enabled AND not explicitly disabled
  if (audioEnabled && !commandsManager.audioDisabled) {
    service.addTrack(commandsManager.audioCodec.toCodec())
  }

  if (videoEnabled) {
    service.addTrack(commandsManager.videoCodec.toCodec())
  }

  service.generatePmt()
  psiManager.updateService(service)

  Log.i(TAG, "Track config: video=$videoEnabled, audio=${audioEnabled && !commandsManager.audioDisabled}")
}

Workaround

Currently using a local patch to force video-only PSI tables:

private fun setTrackConfig(videoEnabled: Boolean, audioEnabled: Boolean) {
  Pid.reset()
  service.clearTracks()
  if (videoEnabled) service.addTrack(commandsManager.videoCodec.toCodec())
  service.generatePmt()
  psiManager.updateService(service)
  Log.i(TAG, "Track config: video=$videoEnabled, audio=false (forced)")
}

Environment

Library Version: rootProject-SNAPSHOT (latest master)

Android: 13 (API 33)

Video Codec: H265

Audio Codec: AAC

Protocol: SRT

Server: ZLMediaKit (2024)

Related Code

srt/src/main/java/com/pedro/srt/srt/SrtSender.kt (line 69–76, 113)

srt/src/main/java/com/pedro/srt/srt/SrtClient.kt (line 163)

srt/src/main/java/com/pedro/srt/srt/CommandsManager.kt (line 55)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions