diff --git a/viewer/media_player.py b/viewer/media_player.py index fba2db9e0..a9720a6a8 100644 --- a/viewer/media_player.py +++ b/viewer/media_player.py @@ -57,6 +57,44 @@ def is_playing(self): return False +def _detect_hdmi_audio_device(): + """Auto-detect connected HDMI audio device on Pi4/Pi5. + + Pi4 has two HDMI ports: + - HDMI-A-1 = card 1 = vc4hdmi0 + - HDMI-A-2 = card 2 = vc4hdmi1 + + Checks /sys/class/drm/cardN-HDMI-A-N/status to find + which port is connected and returns the matching ALSA device. + Uses sysdefault instead of default for reliable audio output. + """ + import os + + for port, card_name in [ + ('card1-HDMI-A-1', 'vc4hdmi0'), + ('card1-HDMI-A-2', 'vc4hdmi1'), + ]: + status_path = f'/sys/class/drm/{port}/status' + try: + if os.path.exists(status_path): + with open(status_path) as f: + if f.read().strip() == 'connected': + logging.info( + 'Detected connected HDMI: %s -> ' + 'sysdefault:CARD=%s', + port, + card_name, + ) + return f'sysdefault:CARD={card_name}' + except OSError: + pass + + logging.warning( + 'No connected HDMI detected, falling back to sysdefault:CARD=vc4hdmi0', + ) + return 'sysdefault:CARD=vc4hdmi0' + + class VLCMediaPlayer(MediaPlayer): def __init__(self): MediaPlayer.__init__(self) @@ -70,16 +108,16 @@ def __init__(self): def get_alsa_audio_device(self): if settings['audio_output'] == 'local': if get_device_type() == 'pi5': - return 'default:CARD=vc4hdmi0' + return 'sysdefault:CARD=vc4hdmi0' return 'plughw:CARD=Headphones' else: if get_device_type() in ['pi4', 'pi5']: - return 'default:CARD=vc4hdmi0' + return _detect_hdmi_audio_device() elif get_device_type() in ['pi1', 'pi2', 'pi3']: - return 'default:CARD=vc4hdmi' + return 'sysdefault:CARD=vc4hdmi' else: - return 'default:CARD=HID' + return 'sysdefault:CARD=HID' def __get_options(self): return [