【山大会议】软件性能优化及bug修复

序言

这篇文章主要用于记录几个项目中客户端代码的性能优化以及恶性bug的修复

修改 WebRTC 编码器

2022年5月30日

在测试中发现,软件在进行视频通话时,CPU 负载较高,经过检测发现是由于 WebRTC 默认使用 VP8 的编码器、解码器。为了降低 CPU 负载,我允许用户自行选择使用 CPU 或是 GPU 进行渲染。当使用 GPU 进行视频渲染时,会使用 H264 的编码器进行实现。

// NOTE: 支持的编码器
const senderCodecs = RTCRtpSender.getCapabilities('video')?.codecs as RTCRtpCodecCapability[];
const receiverCodecs = RTCRtpReceiver.getCapabilities('video')?.codecs as RTCRtpCodecCapability[];
(() => {
    
    
	const senderH264Index = senderCodecs?.findIndex(
		(c) =>
			c.mimeType === 'video/H264' &&
			c.sdpFmtpLine ===
				'level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f'
	);
	const senderH264 = (senderCodecs as Array<RTCRtpCodecCapability>)[
		senderH264Index ? senderH264Index : 0
	];
	senderCodecs?.splice(senderH264Index ? senderH264Index : 0, 1);
	senderCodecs?.unshift(senderH264);

	const receiverH264Index = receiverCodecs?.findIndex(
		(c) =>
			c.mimeType === 'video/H264' &&
			c.sdpFmtpLine ===
				'level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f'
	);
	const receiverH264 = (receiverCodecs as Array<RTCRtpCodecCapability>)[
		receiverH264Index ? receiverH264Index : 0
	];
	receiverCodecs?.splice(receiverH264Index ? receiverH264Index : 0, 1);
	receiverCodecs?.unshift(receiverH264);
})();
export {
    
     senderCodecs, receiverCodecs };

将编码器进行保存,如果有需要则使用 H264 的编码器/解码器。

用户缺失部分多媒体设备

2022年6月2日

由于我们的 WebRTC 默认用户上传音视频两条轨道,一旦用户不具备某种设备可能会导致整套流程无法走下去。为了缓解这种情况,我将获取媒体流失败的情况进行了 try...catch 操作,并将返回一个默认的媒体流。

let defaultVideoWidget: HTMLVideoElement | undefined;
function getDefaultStream(): Promise<MediaStream> {
    
    
	return new Promise((resolve) => {
    
    
		if (defaultVideoWidget) {
    
    
			resolve((defaultVideoWidget as any).captureStream(1) as MediaStream);
		} else {
    
    
			defaultVideoWidget = document.createElement('video');
			defaultVideoWidget.autoplay = true;
			defaultVideoWidget.src = '../electronAssets/null.mp4';
			defaultVideoWidget.loop = true;
			defaultVideoWidget.onloadedmetadata = () => {
    
    
				resolve((defaultVideoWidget as any).captureStream(1) as MediaStream);
			};
		}
	});
}

消息提示音 Bug 修复

2022年6月4日

由于我们的消息提示音使用了 AudioContext 实现,其中具有大量的异步操作。在最初的开发中我没有意识到这样的异步操作带来的问题,在后续的测试中才发现异步操作导致停止播放很难正常起到作用。因此,针对异步操作,我将消息提示音的代码修改为了下方的版本:

// Prompt.ts
export const AUDIO_TYPE = {
    
    
	MESSAGE_RECEIVED: 'info',
	WEBRTC_CALLING: 'call',
	WEBRTC_ANSWERING: 'answer',
};

export const buildPropmt = function (audioType: string, loop = false) {
    
    
	const audioContext = new AudioContext();
	let source = audioContext.createBufferSource();
	const audio = require(`./audios/${
      
      audioType}.aac`);

	let abortController = new AbortController();
	let abortSignal = abortController.signal;

	const startAudioPropmt = () => {
    
    
		if (source.buffer) {
    
    
			source.stop();
			source = audioContext.createBufferSource();
		}
		fetch(audio.default, {
    
    
			signal: abortSignal,
		})
			.then((res) => {
    
    
				return res.arrayBuffer();
			})
			.then((arrayBuffer) => {
    
    
				return audioContext.decodeAudioData(arrayBuffer, (decodeData) => {
    
    
					return decodeData;
				});
			})
			.then((audioBuffer) => {
    
    
				stopAudioPropmt();
				source.buffer = audioBuffer;
				source.loop = loop;
				source.connect(audioContext.destination);
				source.start(0);
			})
			.catch((message) => {
    
    
				console.log(message);
			});
	};

	const stopAudioPropmt = () => {
    
    
		if (source.buffer) {
    
    
			source.stop();
			source = audioContext.createBufferSource();
		} else {
    
    
			abortController.abort();
			abortController = new AbortController();
			abortSignal = abortController.signal;
		}
	};
	return [startAudioPropmt, stopAudioPropmt];
};

现在会优先终止异步操作,防止操作失效导致程序的后续使用中出现无法修复的 bug 。

猜你喜欢

转载自blog.csdn.net/qq_53126706/article/details/125162439