It's funny you should ask this week. I'm the original poster, and I found a technique just days ago that works for us.
When the WebRTC bugtracker was migrated to a new platform last week, the search function became more usable. I found this 2018 nugget:
Setting echoCancellation: {exact: false} worked on all non-Safari browsers I tested on:
+ Win10 (Chrome and Firefox)
+ macOS (Chrome and Firefox)
+ Android 13 Samsung tablet (Chrome)
+ Android 14 Pixel 7 phone (Chrome)
And although it doesn't work on Safari (and all browsers on iOS are just skins of Safari), the following similar technique does work:
noiseSuppression: {exact: false}
There will be an echo (if a mic picks up speaker output from any audio from other attendees), but you might be able to mitigate this if you can mute all but the current active participant.
What's the best way to detect which technique to use? Relying on user-agent parsing is not a good way. One should be able to rely on getCapabilities of the audio input track, but Safari does not include noiseSuppression among its capabilities (although it does work). And getCapabilities is not reliable for 'exact' constraints.
Safari throws an OverconstrainedError if you request echoCancellation:{exact:false}
at least it does for me when also constraining deviceId. But I suspect that wrapping with a try...catch, and constraining noiseSuppression in the catch, will probably work. (To be tested next week.)
Tell us if this works for you.