different paradigm of managing audio

This commit is contained in:
talksik
2022-06-29 10:12:03 -05:00
parent debf274e68
commit e1f03e0efa
6 changed files with 86 additions and 48 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"workbench.colorTheme": "Default Light+", "workbench.colorTheme": "Default Light+",
"javascript.format.semicolons": "insert", "javascript.format.semicolons": "insert",
"window.zoomLevel": 1 "window.zoomLevel": 0
// "eslint.workingDirectories": ["./packages/desktop"] // "eslint.workingDirectories": ["./packages/desktop"]
} }
@@ -63,12 +63,18 @@ function useSocketFire() {
return { handleConnectToLine, handleTuneIntoLine, handleUntuneFromLine }; return { handleConnectToLine, handleTuneIntoLine, handleUntuneFromLine };
} }
const videoConstraints = { const VIDEO_CONSTRAINTS = {
frameRate: 15, frameRate: 15,
width: { max: 720, ideal: 720, min: 100 }, width: { max: 720, ideal: 720, min: 100 },
height: { max: 720, ideal: 720, min: 100 }, height: { max: 720, ideal: 720, min: 100 },
}; };
const AUDIO_CONSTRAINTS = {
channelCount: {
ideal: 2,
},
};
interface IConversationContext { interface IConversationContext {
conversationMap: ConversationMap; conversationMap: ConversationMap;
@@ -86,8 +92,7 @@ interface IConversationContext {
updateConversationPriority?: (conversationId: string, newState: MemberState) => Promise<void>; updateConversationPriority?: (conversationId: string, newState: MemberState) => Promise<void>;
userLocalStream?: MediaStream; userLocalStream?: MediaStream;
handleCastVideo?: () => void; handleToggleVideo?: () => void;
handleStopVideo?: () => void;
} }
const ConversationContext = React.createContext<IConversationContext>({ const ConversationContext = React.createContext<IConversationContext>({
@@ -298,6 +303,9 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
return conversationToSelect; return conversationToSelect;
}); });
// !!TODO: go through each peer connection in the selected room and add the current stream
// remove/stop casting stream to previously selected room
}, },
[ [
user, user,
@@ -447,27 +455,57 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
); );
const [userLocalStream, setUserLocalStream] = useState<MediaStream>(); const [userLocalStream, setUserLocalStream] = useState<MediaStream>();
const [userVideo, setUserVideo] = useState<boolean>(true);
const [userAudio, setUserAudio] = useState<boolean>(true);
const handleCastVideo = useCallback(() => { useEffect(() => {
// create a new stream // want to grab device stream even if not selected a room
// if there's a selected conversation, then send it to that conversation // only upload this stream to a room if we have a selected room
navigator.mediaDevices
.getUserMedia({ video: videoConstraints, audio: false })
.then((userStream: MediaStream) => {
setUserLocalStream(userStream);
})
.catch((error) => toast.error('problem getting video'));
}, [setUserLocalStream]);
const handleStopVideo = useCallback(() => { if (userVideo || userAudio) {
setUserLocalStream((prevStream) => { navigator.mediaDevices
if (prevStream) { .getUserMedia({
prevStream.getTracks().map((track) => track.stop()); audio: userAudio ? AUDIO_CONSTRAINTS : false,
} video: userVideo ? VIDEO_CONSTRAINTS : false,
})
.then((userStream) => {
console.log(`got new user stream`, userStream);
return undefined; // set global stream for slight feedback while talking
}); setUserLocalStream(userStream);
}, [setUserLocalStream]); });
} else {
setUserLocalStream(undefined);
// stop streaming to room now
}
}, [userVideo, userAudio, setUserLocalStream]);
useEffect(() => {
if (!userAudio) {
userLocalStream.getAudioTracks().map((track) => track.stop());
}
}, [userAudio, userLocalStream]);
useEffect(() => {
if (!userVideo) {
userLocalStream.getVideoTracks().map((track) => track.stop());
}
}, [userVideo, userLocalStream]);
// take the local stream and use simple peer add track
const handleToggleAudio = useCallback(() => {
setUserAudio((prevVal) => !prevVal);
}, []);
const handleToggleVideo = useCallback(() => {
setUserVideo((prevVal) => !prevVal);
}, [setUserVideo]);
// TODO: replace track of the same stream and
const handleShareScreen = useCallback(() => {
//
}, []);
useKeyPressEvent(KeyboardShortcuts.speak.shortcutKey, handleToggleAudio, handleToggleAudio);
const handleEscape = useCallback(() => { const handleEscape = useCallback(() => {
selectConversation(undefined); selectConversation(undefined);
@@ -508,8 +546,7 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
handleEscape, handleEscape,
updateConversationPriority: updateConversationPriorityHandler, updateConversationPriority: updateConversationPriorityHandler,
userLocalStream, userLocalStream,
handleStopVideo, handleToggleVideo,
handleCastVideo,
}} }}
> >
{children} {children}
+16 -19
View File
@@ -46,13 +46,8 @@ import useZen from '../providers/ZenProvider';
export default function FooterControls() { export default function FooterControls() {
const { handleFlowState } = useZen(); const { handleFlowState } = useZen();
const { const { selectedConversation, priorityConversations, userLocalStream, handleToggleVideo } =
selectedConversation, useConversations();
priorityConversations,
userLocalStream,
handleCastVideo,
handleStopVideo,
} = useConversations();
const { user, handleLogout } = useAuth(); const { user, handleLogout } = useAuth();
const { handleToggleDesktopMode, desktopMode } = useElectron(); const { handleToggleDesktopMode, desktopMode } = useElectron();
@@ -82,17 +77,17 @@ export default function FooterControls() {
const [isVideoOn, setIsVideoOn] = useState<boolean>(false); const [isVideoOn, setIsVideoOn] = useState<boolean>(false);
const handleToggleVideo = useCallback(() => { // const handleToggleVideo = useCallback(() => {
setIsVideoOn((prevVal) => { // setIsVideoOn((prevVal) => {
if (!prevVal) { // if (!prevVal) {
handleCastVideo(); // handleCastVideo();
} else { // } else {
handleStopVideo(); // handleStopVideo();
} // }
return !prevVal; // return !prevVal;
}); // });
}, [setIsVideoOn, handleCastVideo, handleStopVideo]); // }, [setIsVideoOn, handleCastVideo, handleStopVideo]);
const handleCloseUserSettings = useCallback(() => { const handleCloseUserSettings = useCallback(() => {
setOpenUserSettings(false); setOpenUserSettings(false);
@@ -183,7 +178,7 @@ export default function FooterControls() {
aria-haspopup="true" aria-haspopup="true"
aria-expanded={open ? 'true' : undefined} aria-expanded={open ? 'true' : undefined}
> >
{isVideoOn ? ( {userLocalStream ? (
<Box height={60} width={40} ref={localVideoRef} component={'video'} autoPlay /> <Box height={60} width={40} ref={localVideoRef} component={'video'} autoPlay />
) : ( ) : (
<Avatar alt={user.givenName} src={user.picture} /> <Avatar alt={user.givenName} src={user.picture} />
@@ -243,7 +238,9 @@ function OverlayConversation({
const userVideoRef = useRef<HTMLVideoElement>(null); const userVideoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {}, []); useEffect(() => {
//
}, []);
return ( return (
<Stack <Stack
+2 -2
View File
@@ -308,7 +308,7 @@ function ConversationDetails({ masterConversation }: { masterConversation: Maste
<Box sx={{ p: 2, boxShadow: 3, zIndex: 5 }} flexDirection={'column'} mt={'auto'}> <Box sx={{ p: 2, boxShadow: 3, zIndex: 5 }} flexDirection={'column'} mt={'auto'}>
{/* live video and screenshares */} {/* live video and screenshares */}
<Stack direction="row" alignItems={'center'}> <Stack direction="row" alignItems={'center'}>
{masterConversation.room && {/* {masterConversation.room &&
Object.entries(masterConversation.room).map(([userId, userPeerContents]) => { Object.entries(masterConversation.room).map(([userId, userPeerContents]) => {
return ( return (
<Video <Video
@@ -316,7 +316,7 @@ function ConversationDetails({ masterConversation }: { masterConversation: Maste
stream={userPeerContents.stream} stream={userPeerContents.stream}
/> />
); );
})} })} */}
</Stack> </Stack>
<Stack direction="row" alignItems="center" justifyContent={'flex-end'} gap={1}> <Stack direction="row" alignItems="center" justifyContent={'flex-end'} gap={1}>
+4
View File
@@ -9,4 +9,8 @@ export const KeyboardShortcuts: Record<string, Shortcut> = {
shortcutKey: 'Escape', shortcutKey: 'Escape',
label: 'esc', label: 'esc',
}, },
speak: {
shortcutKey: '`',
label: '~',
},
}; };
+3 -3
View File
@@ -15,15 +15,15 @@ export type MasterConversation = Conversation & {
room?: { room?: {
[userId: string]: { [userId: string]: {
peer: Peer; peer: Peer;
//the remote stream of this peer
stream?: MediaStream; stream?: MediaStream;
audioTrack?: MediaStreamTrack;
videoTrack?: MediaStreamTrack;
screenTrack?: MediaStreamTrack;
// calling happening whether it is a newbie or master // calling happening whether it is a newbie or master
isConnecting?: boolean; isConnecting?: boolean;
}; };
}; };
localStream?: MediaStream;
// all of audio clips, links, media, etc. // all of audio clips, links, media, etc.
content?: ContentBlock[]; content?: ContentBlock[];