Remove audio element from VideoFeed

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
pull/21833/head
Šimon Brandner 2021-04-27 12:02:41 +02:00
parent b612b252e1
commit f3a7ffca60
No known key found for this signature in database
GPG Key ID: 9760693FDD98A790
1 changed files with 16 additions and 51 deletions

View File

@ -21,7 +21,6 @@ import SettingsStore from "../../../settings/SettingsStore";
import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed'; import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed';
import { logger } from 'matrix-js-sdk/src/logger'; import { logger } from 'matrix-js-sdk/src/logger';
import MemberAvatar from "../avatars/MemberAvatar" import MemberAvatar from "../avatars/MemberAvatar"
import CallMediaHandler from "../../../CallMediaHandler";
import {replaceableComponent} from "../../../utils/replaceableComponent"; import {replaceableComponent} from "../../../utils/replaceableComponent";
interface IProps { interface IProps {
@ -45,11 +44,9 @@ interface IState {
videoMuted: boolean; videoMuted: boolean;
} }
@replaceableComponent("views.voip.VideoFeed") @replaceableComponent("views.voip.VideoFeed")
export default class VideoFeed extends React.Component<IProps, IState> { export default class VideoFeed extends React.Component<IProps, IState> {
private video = createRef<HTMLVideoElement>(); private element = createRef<HTMLVideoElement>();
private audio = createRef<HTMLAudioElement>();
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
@ -62,38 +59,20 @@ export default class VideoFeed extends React.Component<IProps, IState> {
componentDidMount() { componentDidMount() {
this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream);
this.playAllMedia(); this.playMedia();
} }
componentWillUnmount() { componentWillUnmount() {
this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream);
this.video.current?.removeEventListener('resize', this.onResize); this.element.current?.removeEventListener('resize', this.onResize);
this.stopAllMedia(); this.stopMedia();
} }
private playMediaElement(element: HTMLVideoElement | HTMLAudioElement) { private playMedia() {
if (element instanceof HTMLAudioElement) { const element = this.element.current;
const audioOutput = CallMediaHandler.getAudioOutput(); if (!element) return;
// We play audio in AudioFeed, not here
// Don't play audio if the feed is local
element.muted = this.props.feed.isLocal();
if (audioOutput && !element.muted) {
try {
// This seems quite unreliable in Chrome, although I haven't yet managed to make a jsfiddle where
// it fails.
// It seems reliable if you set the sink ID after setting the srcObject and then set the sink ID
// back to the default after the call is over - Dave
element.setSinkId(audioOutput);
} catch (e) {
console.error("Couldn't set requested audio output device: using default", e);
logger.warn("Couldn't set requested audio output device: using default", e);
}
}
} else {
element.muted = true; element.muted = true;
}
element.srcObject = this.props.feed.stream; element.srcObject = this.props.feed.stream;
element.autoplay = true; element.autoplay = true;
try { try {
@ -112,7 +91,10 @@ export default class VideoFeed extends React.Component<IProps, IState> {
} }
} }
private stopMediaElement(element: HTMLAudioElement | HTMLVideoElement) { private stopMedia() {
const element = this.element.current;
if (!element) return;
element.pause(); element.pause();
element.src = null; element.src = null;
@ -122,22 +104,12 @@ export default class VideoFeed extends React.Component<IProps, IState> {
// seem to be necessary - Šimon // seem to be necessary - Šimon
} }
private playAllMedia() {
this.playMediaElement(this.audio.current);
if (this.video.current) this.playMediaElement(this.video.current);
}
private stopAllMedia() {
this.stopMediaElement(this.audio.current)
if (this.video.current) this.stopMediaElement(this.video.current);
}
private onNewStream = () => { private onNewStream = () => {
this.setState({ this.setState({
audioMuted: this.props.feed.isAudioMuted(), audioMuted: this.props.feed.isAudioMuted(),
videoMuted: this.props.feed.isVideoMuted(), videoMuted: this.props.feed.isVideoMuted(),
}); });
this.playAllMedia(); this.playMedia();
}; };
private onResize = (e) => { private onResize = (e) => {
@ -152,16 +124,13 @@ export default class VideoFeed extends React.Component<IProps, IState> {
mx_VideoFeed_local: this.props.feed.isLocal(), mx_VideoFeed_local: this.props.feed.isLocal(),
mx_VideoFeed_remote: !this.props.feed.isLocal(), mx_VideoFeed_remote: !this.props.feed.isLocal(),
mx_VideoFeed_voice: this.state.videoMuted, mx_VideoFeed_voice: this.state.videoMuted,
mx_VideoFeed_video: !this.state.videoMuted,
mx_VideoFeed_mirror: ( mx_VideoFeed_mirror: (
this.props.feed.isLocal() && this.props.feed.isLocal() &&
SettingsStore.getValue('VideoView.flipVideoHorizontally') SettingsStore.getValue('VideoView.flipVideoHorizontally')
), ),
}; };
const audio = (
<audio ref={this.audio} />
);
if (this.state.videoMuted) { if (this.state.videoMuted) {
const member = this.props.feed.getMember(); const member = this.props.feed.getMember();
const avatarSize = this.props.pipMode ? 76 : 160; const avatarSize = this.props.pipMode ? 76 : 160;
@ -173,15 +142,11 @@ export default class VideoFeed extends React.Component<IProps, IState> {
height={avatarSize} height={avatarSize}
width={avatarSize} width={avatarSize}
/> />
{audio}
</div> </div>
); );
} else { } else {
return ( return (
<div className={classnames(videoClasses)}> <video className={classnames(videoClasses)} ref={this.element} />
<video className="mx_VideoFeed_video" ref={this.video} />
{audio}
</div>
); );
} }
} }