mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-28 19:06:52 +03:00
fix two-way talk on cameras with AAC audio
The mic button was enabled whenever WebRTC was globally available, but the live view only switched to the WebRTC player when the stream itself qualified for WebRTC, and AAC playback audio disqualifies it. On most cameras the mic showed as on while nothing was sent. Two-way talk only needs the stream's video to connect since the backchannel is sent, not received, so AAC playback audio no longer blocks it. The mic is also turned off when a stream switch makes talk unavailable.
This commit is contained in:
@@ -27,10 +27,7 @@ import {
|
||||
} from "@/components/ui/popover";
|
||||
import { useResizeObserver } from "@/hooks/resize-observer";
|
||||
import useKeyboardListener from "@/hooks/use-keyboard-listener";
|
||||
import {
|
||||
useWebRTCAvailableForStream,
|
||||
useWebRTCGloballyAvailable,
|
||||
} from "@/hooks/use-webrtc-availability";
|
||||
import { useWebRTCAvailableForStream } from "@/hooks/use-webrtc-availability";
|
||||
import { CameraConfig, FrigateConfig } from "@/types/frigateConfig";
|
||||
import {
|
||||
LivePlayerError,
|
||||
@@ -219,15 +216,16 @@ export default function LiveCameraView({
|
||||
);
|
||||
const isWebRTCAvailable = webRTCAvailability.available;
|
||||
|
||||
// Two-way talk is the sendonly backchannel: global, not per-stream.
|
||||
const { globallyAvailable: webRTCGloballyAvailable } =
|
||||
useWebRTCGloballyAvailable();
|
||||
|
||||
// "checking" means the probe has not answered yet, and it re-enters that on
|
||||
// every mount, so treating it as unavailable downgrades the saved choice.
|
||||
const webRTCVerdictPending = webRTCAvailability.reason === "checking";
|
||||
const webRTCUsable = isWebRTCAvailable || webRTCVerdictPending;
|
||||
|
||||
// Two-way talk is a sendonly backchannel, so playback audio that WebRTC
|
||||
// can't carry doesn't rule it out, but the stream's video must connect
|
||||
const talkAvailable =
|
||||
isWebRTCAvailable || webRTCAvailability.reason === "audio-codec";
|
||||
|
||||
// Resolves the saved preference without overwriting it. Transient error
|
||||
// fallbacks layer on top in preferredLiveMode.
|
||||
const resolvedUserMode = useMemo<LivePlayerMode>(() => {
|
||||
@@ -398,6 +396,14 @@ export default function LiveCameraView({
|
||||
|
||||
const [audio, setAudio] = useSessionPersistence("liveAudio", false);
|
||||
const [mic, setMic] = useState(false);
|
||||
|
||||
// the mic only connects through the WebRTC player, so it can't stay on
|
||||
// for a stream that has lost it
|
||||
useEffect(() => {
|
||||
if (!talkAvailable) {
|
||||
setMic(false);
|
||||
}
|
||||
}, [talkAvailable]);
|
||||
const [webRTC, setWebRTC] = useState(false);
|
||||
const [pip, setPip] = useState(false);
|
||||
const [lowBandwidth, setLowBandwidth] = useState(false);
|
||||
@@ -424,7 +430,7 @@ export default function LiveCameraView({
|
||||
});
|
||||
|
||||
const preferredLiveMode = useMemo(() => {
|
||||
if (mic && isWebRTCAvailable) {
|
||||
if (mic && talkAvailable) {
|
||||
return "webrtc";
|
||||
}
|
||||
|
||||
@@ -456,6 +462,7 @@ export default function LiveCameraView({
|
||||
lowBandwidth,
|
||||
forceLowBandwidth,
|
||||
mic,
|
||||
talkAvailable,
|
||||
webRTC,
|
||||
isRestreamed,
|
||||
resolvedUserMode,
|
||||
@@ -489,7 +496,7 @@ export default function LiveCameraView({
|
||||
}
|
||||
break;
|
||||
case "t":
|
||||
if (supports2WayTalk) {
|
||||
if (supports2WayTalk && talkAvailable) {
|
||||
setMic(!mic);
|
||||
return true;
|
||||
}
|
||||
@@ -737,11 +744,15 @@ export default function LiveCameraView({
|
||||
Icon={mic ? FaMicrophone : FaMicrophoneSlash}
|
||||
isActive={mic}
|
||||
title={
|
||||
!webRTCGloballyAvailable
|
||||
? t("twoWayTalk.requiresWebRTC", { ns: "views/live" })
|
||||
: mic
|
||||
? t("twoWayTalk.disable", { ns: "views/live" })
|
||||
: t("twoWayTalk.enable", { ns: "views/live" })
|
||||
webRTCVerdictPending
|
||||
? t("stream.technology.unavailable.checking", {
|
||||
ns: "views/live",
|
||||
})
|
||||
: !talkAvailable
|
||||
? t("twoWayTalk.requiresWebRTC", { ns: "views/live" })
|
||||
: mic
|
||||
? t("twoWayTalk.disable", { ns: "views/live" })
|
||||
: t("twoWayTalk.enable", { ns: "views/live" })
|
||||
}
|
||||
onClick={() => {
|
||||
setMic(!mic);
|
||||
@@ -749,7 +760,7 @@ export default function LiveCameraView({
|
||||
setAudio(true);
|
||||
}
|
||||
}}
|
||||
disabled={!cameraEnabled || debug || !webRTCGloballyAvailable}
|
||||
disabled={!cameraEnabled || debug || !talkAvailable}
|
||||
/>
|
||||
)}
|
||||
{supportsAudioOutput && preferredLiveMode != "jsmpeg" && (
|
||||
|
||||
Reference in New Issue
Block a user