fix: Don't detect audio from stale webrtc connection (#2429)
- Closes: #2417
This commit is contained in:
committed by
dermotduffy
parent
55732ead1d
commit
9535bb8aa0
+5
-3
@@ -39,10 +39,12 @@ export const hasAudio = (
|
|||||||
// We check that the track is not muted because muted means no media data
|
// We check that the track is not muted because muted means no media data
|
||||||
// is flowing (e.g., the source isn't producing audio). It is not related to
|
// is flowing (e.g., the source isn't producing audio). It is not related to
|
||||||
// the audio being muted by the user on the receiving end.
|
// the audio being muted by the user on the receiving end.
|
||||||
if (pc) {
|
// Only trust receivers when the connection is actually established — a stale
|
||||||
|
// RTCPeerConnection (e.g. WebRTC failed, fell back to MSE) will have
|
||||||
|
// receivers with muted tracks that don't reflect actual media availability.
|
||||||
|
// See: https://github.com/dermotduffy/advanced-camera-card/issues/2417
|
||||||
|
if (pc && pc.connectionState === 'connected') {
|
||||||
const receivers = pc.getReceivers();
|
const receivers = pc.getReceivers();
|
||||||
|
|
||||||
// Only trust receivers if they're populated (connection established)
|
|
||||||
if (receivers.length > 0) {
|
if (receivers.length > 0) {
|
||||||
return receivers.some(
|
return receivers.some(
|
||||||
(receiver) => receiver.track?.kind === 'audio' && !receiver.track?.muted,
|
(receiver) => receiver.track?.kind === 'audio' && !receiver.track?.muted,
|
||||||
|
|||||||
@@ -1793,6 +1793,24 @@ describe('MenuButtonController', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not have mute button without audio', () => {
|
||||||
|
const mediaPlayerController = mock<MediaPlayerController>();
|
||||||
|
const buttons = calculateButtons(controller, {
|
||||||
|
currentMediaLoadedInfo: createMediaLoadedInfo({
|
||||||
|
capabilities: {
|
||||||
|
hasAudio: false,
|
||||||
|
},
|
||||||
|
mediaPlayerController,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(buttons).not.toContainEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
title: 'Mute / Unmute',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should have screenshot button', () => {
|
it('should have screenshot button', () => {
|
||||||
const buttons = calculateButtons(controller, {
|
const buttons = calculateButtons(controller, {
|
||||||
currentMediaLoadedInfo: createMediaLoadedInfo({
|
currentMediaLoadedInfo: createMediaLoadedInfo({
|
||||||
|
|||||||
@@ -82,8 +82,12 @@ describe('hasAudio', () => {
|
|||||||
} as unknown as RTCRtpReceiver;
|
} as unknown as RTCRtpReceiver;
|
||||||
};
|
};
|
||||||
|
|
||||||
const createMockPeerConnection = (receivers: RTCRtpReceiver[]): RTCPeerConnection => {
|
const createMockPeerConnection = (
|
||||||
|
receivers: RTCRtpReceiver[],
|
||||||
|
connectionState: RTCPeerConnectionState = 'connected',
|
||||||
|
): RTCPeerConnection => {
|
||||||
return {
|
return {
|
||||||
|
connectionState,
|
||||||
getReceivers: () => receivers,
|
getReceivers: () => receivers,
|
||||||
} as unknown as RTCPeerConnection;
|
} as unknown as RTCPeerConnection;
|
||||||
};
|
};
|
||||||
@@ -116,6 +120,21 @@ describe('hasAudio', () => {
|
|||||||
// With no properties set on video, mayHaveAudio returns true (generous default)
|
// With no properties set on video, mayHaveAudio returns true (generous default)
|
||||||
expect(hasAudio(createMockVideo(), pc, '')).toBe(true);
|
expect(hasAudio(createMockVideo(), pc, '')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should ignore receivers when connection is not established', () => {
|
||||||
|
const pc = createMockPeerConnection([createMockReceiver('audio', true)], 'new');
|
||||||
|
|
||||||
|
// Stale connection with muted receiver should fall through to
|
||||||
|
// mayHaveAudio (generous default returns true)
|
||||||
|
expect(hasAudio(createMockVideo(), pc, '')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fall through to mseCodecs when connection is not established', () => {
|
||||||
|
const pc = createMockPeerConnection([createMockReceiver('audio', true)], 'new');
|
||||||
|
|
||||||
|
// Stale WebRTC connection but MSE has audio codecs
|
||||||
|
expect(hasAudio(createMockVideo(), pc, 'avc1.640029,flac')).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('MSE codec detection', () => {
|
describe('MSE codec detection', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user