mirror of
https://github.com/Vencord/Vesktop.git
synced 2025-02-22 21:35:08 +00:00
feat: allow patching video & audio devices into screen share
This commit is contained in:
parent
5b6c1c6d81
commit
5133e70717
2 changed files with 123 additions and 15 deletions
|
@ -21,6 +21,7 @@ import {
|
|||
} from "@vencord/types/webpack/common";
|
||||
import { Node } from "@vencord/venmic";
|
||||
import type { Dispatch, SetStateAction } from "react";
|
||||
import { patchOverrideDevices } from "renderer/patches/screenShareFixes";
|
||||
import { addPatch } from "renderer/patches/shared";
|
||||
import { useSettings } from "renderer/settings";
|
||||
import { isLinux, isWindows } from "renderer/utils";
|
||||
|
@ -47,6 +48,8 @@ interface StreamSettings {
|
|||
resolution: StreamResolution;
|
||||
fps: StreamFps;
|
||||
audio: boolean;
|
||||
overrideAudioDevice?: string;
|
||||
overrideVideoDevice?: string;
|
||||
contentHint?: string;
|
||||
includeSources?: AudioSources;
|
||||
excludeSources?: AudioSources;
|
||||
|
@ -140,6 +143,11 @@ export function openScreenSharePicker(screens: Source[], skipPicker: boolean) {
|
|||
}
|
||||
}
|
||||
|
||||
patchOverrideDevices({
|
||||
audio: v.overrideAudioDevice,
|
||||
video: v.overrideVideoDevice
|
||||
});
|
||||
|
||||
resolve(v);
|
||||
}}
|
||||
close={() => {
|
||||
|
@ -325,6 +333,16 @@ function StreamSettings({
|
|||
}
|
||||
);
|
||||
|
||||
const [audioDevices, , audioDevicesPending] = useAwaiter(
|
||||
() => navigator.mediaDevices.enumerateDevices().then(g => g.filter(d => d.kind === "audioinput")),
|
||||
{ fallbackValue: [] }
|
||||
);
|
||||
|
||||
const [videoDevices, , videoDevicesPending] = useAwaiter(
|
||||
() => navigator.mediaDevices.enumerateDevices().then(g => g.filter(d => d.kind === "videoinput")),
|
||||
{ fallbackValue: [] }
|
||||
);
|
||||
|
||||
const openSettings = () => {
|
||||
const key = openModal(props => (
|
||||
<AudioSettingsModal
|
||||
|
@ -428,6 +446,47 @@ function StreamSettings({
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Forms.FormTitle>
|
||||
{audioDevicesPending ? "Loading audio devices..." : "Audio devices"}
|
||||
</Forms.FormTitle>
|
||||
<Select
|
||||
options={audioDevices.map(({ label, deviceId }) => ({
|
||||
label,
|
||||
value: deviceId
|
||||
}))}
|
||||
isSelected={d => settings.overrideAudioDevice === d}
|
||||
select={d => {
|
||||
setSettings(v => ({ ...v, overrideAudioDevice: d }));
|
||||
}}
|
||||
serialize={String}
|
||||
popoutPosition="top"
|
||||
closeOnSelect={true}
|
||||
isDisabled={audioDevicesPending}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Forms.FormTitle>
|
||||
{videoDevicesPending ? "Loading video devices..." : "Video devices"}
|
||||
</Forms.FormTitle>
|
||||
<Select
|
||||
options={videoDevices.map(({ label, deviceId }) => ({
|
||||
label,
|
||||
value: deviceId
|
||||
}))}
|
||||
isSelected={d => settings.overrideVideoDevice === d}
|
||||
select={d => {
|
||||
setSettings(v => ({ ...v, overrideVideoDevice: d }));
|
||||
}}
|
||||
serialize={String}
|
||||
popoutPosition="top"
|
||||
closeOnSelect={true}
|
||||
isDisabled={videoDevicesPending}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isWindows && (
|
||||
<Switch
|
||||
value={settings.audio}
|
||||
|
|
|
@ -10,21 +10,70 @@ import { isLinux } from "renderer/utils";
|
|||
|
||||
const logger = new Logger("VesktopStreamFixes");
|
||||
|
||||
if (isLinux) {
|
||||
const original = navigator.mediaDevices.getDisplayMedia;
|
||||
const original = navigator.mediaDevices.getDisplayMedia;
|
||||
|
||||
async function getVirtmic() {
|
||||
try {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const audioDevice = devices.find(({ label }) => label === "vencord-screen-share");
|
||||
return audioDevice?.deviceId;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
interface OverrideDevices {
|
||||
audio: string | undefined;
|
||||
video: string | undefined;
|
||||
}
|
||||
|
||||
let overrideDevices: OverrideDevices = { audio: undefined, video: undefined };
|
||||
|
||||
export const patchOverrideDevices = (newOverrideDevices: OverrideDevices) => {
|
||||
overrideDevices = newOverrideDevices;
|
||||
};
|
||||
|
||||
async function getVirtmic() {
|
||||
try {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const audioDevice = devices.find(({ label }) => label === "vencord-screen-share");
|
||||
return audioDevice?.deviceId;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
navigator.mediaDevices.getDisplayMedia = async function (opts) {
|
||||
const stream = await original.call(this, opts);
|
||||
|
||||
if (overrideDevices.audio) {
|
||||
const audio = await navigator.mediaDevices.getUserMedia({
|
||||
audio: {
|
||||
deviceId: { exact: overrideDevices.audio },
|
||||
autoGainControl: false,
|
||||
echoCancellation: false,
|
||||
noiseSuppression: false
|
||||
}
|
||||
});
|
||||
|
||||
stream.getAudioTracks().forEach(t => {
|
||||
t.stop();
|
||||
stream.removeTrack(t);
|
||||
});
|
||||
|
||||
audio.getAudioTracks().forEach(t => {
|
||||
stream.addTrack(t);
|
||||
});
|
||||
}
|
||||
|
||||
navigator.mediaDevices.getDisplayMedia = async function (opts) {
|
||||
const stream = await original.call(this, opts);
|
||||
if (overrideDevices.video) {
|
||||
const video = await navigator.mediaDevices.getUserMedia({
|
||||
video: {
|
||||
deviceId: { exact: overrideDevices.video }
|
||||
}
|
||||
});
|
||||
|
||||
stream.getVideoTracks().forEach(t => {
|
||||
t.stop();
|
||||
stream.removeTrack(t);
|
||||
});
|
||||
|
||||
video.getVideoTracks().forEach(t => {
|
||||
stream.addTrack(t);
|
||||
});
|
||||
}
|
||||
|
||||
if (isLinux) {
|
||||
const id = await getVirtmic();
|
||||
|
||||
const frameRate = Number(currentSettings?.fps);
|
||||
|
@ -63,7 +112,7 @@ if (isLinux) {
|
|||
});
|
||||
audio.getAudioTracks().forEach(t => stream.addTrack(t));
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
};
|
||||
}
|
||||
return stream;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue