Twilio Programmable Video:当 dominantSpeaker 发生变化时,音频似乎会增加音量并构建静态

Twilio Programmable Video: when dominantSpeaker changes, the audio seems to increase in volume and build static

我已经实现了一个界面,使 dominantSpeaker 能够在主 window 中显示他们的图片,但始终可以听到所有参与者的声音。为此,我不得不在 useEffect() 中注释掉 audioTrack.detach() 我遇到的问题是每次 dominantSpeaker 发生变化时,它似乎都会放大它们的音量并开始产生静态.它变得越来越糟,直到听不见,此时当我重新加载页面时,音频已为我修复。每个参与者都有同样的问题,并且只有刷新页面的个人才能解决该问题。即使所有用户都静音,静电仍然存在。当我进入控制台并删除所有的和标签时,静态仍然存在。

我正在将一个道具传递给参与者组件,如果它是 dominant_window,则该道具为真。我这样做是因为我希望每个演讲者的音频都来自他们的小参与者 window,从而同时允许多个音频流。当我注释掉作为 dominant_window 的参与者时,即使它一开始根本不呈现标签,我也听不到任何声音。

我试过在没有 <audio><video> 组件的情况下渲染它,但我仍然能听到音频。这让我认为音频根本不是来自我设置的音频标签。我的假设是,因为我已经注释掉了 audioTrack.detach() 它会一遍又一遍地向控制音频的任何东西添加相同的 audioTrack,从而增加音量(尽管这不能解释每个人都静音时的静态) ,但是当它在那里时,我一次只能获得 1 个参与者的音频。

音频到底是从哪里来的?我如何监控 whatever/where 呢?如果 audioTrack 是一个控制所有音频的单独项目并允许每个人使用 dominantSpeaker?

同时发言,我如何确保每个人只添加一次 audioTrack

Participant.js

import React, {useState, useEffect, useRef} from 'react';

const Participant = ({  key,
                         dominant_window,
                         user,
                         participant,
                         width,
                         videoEnabled,
                         audioEnabled,
                         onMouseEnter,
                         onMouseLeave,
                         is_fullscreen,
                         tiled,
                     }) => {
    const [videoTracks, setVideoTracks] = useState([]);
    const [audioTracks, setAudioTracks] = useState([]);
    const [hovered, setHovered] = useState(false);

    const videoRef = useRef();
    const audioRef = useRef();

    const trackpubsToTracks = trackMap => {
        const tracks = Array.from(trackMap.values()).map(publication => publication.track);
        return tracks;
    };

    const handleTrackChange =
        useEffect(() => {
            const trackSubscribed = track => {
                if (track.kind === 'video') {
                    setVideoTracks(videoTracks => [...videoTracks, track]);
                } else {
                    setAudioTracks(audioTracks => [...audioTracks, track]);
                }
            };

            const trackUnsubscribed = track => {
                if (track.kind === 'video') {
                    setVideoTracks(videoTracks => videoTracks.filter(v => v !== track));
                } else {
                    setAudioTracks(audioTracks => audioTracks.filter(a => a !== track));
                }
            };
            setVideoTracks(trackpubsToTracks(participant.videoTracks));
            setAudioTracks(trackpubsToTracks(participant.audioTracks));

            participant.on('trackSubscribed', trackSubscribed);
            participant.on('trackUnsubscribed', trackUnsubscribed);

            return () => {
                setVideoTracks([]);
                setAudioTracks([]);
            };
        }, [participant]);

    useEffect(() => {
        const videoTrack = videoTracks[0];
        if (videoTrack) {
            videoTrack.attach(videoRef.current);
            return () => {
                //videoTrack.detach();
            };
        }
    }, [videoTracks]);


    useEffect(() => {
        const audioTrack = audioTracks[0];

        if (audioTrack) {
            audioTrack.attach(audioRef.current);
            return () => {
                //audioTrack.detach();
            };
        }
    }, [audioTracks]);
    
    return (
        <div key={key}
             onMouseEnter={() => {
                 if (onMouseEnter) onMouseEnter();
                 setHovered(true)
             }}
             onMouseLeave={() => {
                 if (onMouseLeave) onMouseLeave();
                 setHovered(false)
             }}
        >

            <video className='participant-video'
                    ref={videoRef}
                    autoPlay={true}
                    style={{
                        transform: participant.identity == `u_${user.id}` ? "scaleX(-1)" : "scaleX(1)",
                        opacity: videoEnabled ? "1" : "0",
                        zIndex: videoEnabled ? "1" : "-1"
                    }}/>
            {(audioEnabled && !dominant_window && !(participant.identity == `u_${user.id}`)) && <audio ref={audioRef} autoPlay={true} muted={false}/>}
        </div>
    );
};

export default Participant;

似乎每次 dominantSpeaker 改变时它都在重新附加轨道,复制它。音量和静电的增加是由于它在自身之上播放相同的曲目。