Improve handling of backchannel audio in camera wizard (#21250)

* Improve handling of backchannel audio in camera wizard

* Cleanup

* look for backchannel on all registered streams on save

avoids potential issues with a timeout in stream registration

---------

Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
This commit is contained in:
Nicolas Mowen
2025-12-13 07:12:37 -07:00
committed by GitHub
co-authored by Josh Hawkins
parent 6b9b3778f5
commit 8ddcbf9a8d
7 changed files with 137 additions and 59 deletions
+51 -2
View File
@@ -1,5 +1,6 @@
import { baseUrl } from "@/api/baseUrl";
import { generateFixedHash, isValidId } from "./stringUtil";
import type { LiveStreamMetadata } from "@/types/live";
/**
* Processes a user-entered camera name and returns both the final camera name
@@ -27,8 +28,6 @@ export function processCameraName(userInput: string): {
};
}
// ==================== Reolink Camera Detection ====================
/**
* Detect Reolink camera capabilities and recommend optimal protocol
*
@@ -98,3 +97,53 @@ export function maskUri(uri: string): string {
}
return uri;
}
/**
* Represents the audio features supported by a camera stream
*/
export type CameraAudioFeatures = {
twoWayAudio: boolean;
audioOutput: boolean;
};
/**
* Detects camera audio features from go2rtc stream metadata.
* Checks for two-way audio (backchannel) and audio output capabilities.
*
* @param metadata - The LiveStreamMetadata from go2rtc stream
* @param requireSecureContext - If true, two-way audio requires secure context (default: true)
* @returns CameraAudioFeatures object with detected capabilities
*/
export function detectCameraAudioFeatures(
metadata: LiveStreamMetadata | null | undefined,
requireSecureContext: boolean = true,
): CameraAudioFeatures {
if (!metadata) {
return {
twoWayAudio: false,
audioOutput: false,
};
}
const twoWayAudio =
(!requireSecureContext || window.isSecureContext) &&
metadata.producers.find(
(prod) =>
prod.medias &&
prod.medias.find((media) => media.includes("audio, sendonly")) !=
undefined,
) != undefined;
const audioOutput =
metadata.producers.find(
(prod) =>
prod.medias &&
prod.medias.find((media) => media.includes("audio, recvonly")) !=
undefined,
) != undefined;
return {
twoWayAudio: !!twoWayAudio,
audioOutput: !!audioOutput,
};
}