diff --git a/packages/frontend/src/scripts/sound.ts b/packages/frontend/src/scripts/sound.ts
index 47ec4171af..d28d629227 100644
--- a/packages/frontend/src/scripts/sound.ts
+++ b/packages/frontend/src/scripts/sound.ts
@@ -5,7 +5,7 @@
 
 import { defaultStore } from '@/store.js';
 
-const ctx = new AudioContext();
+let ctx: AudioContext;
 const cache = new Map<string, AudioBuffer>();
 let canPlay = true;
 
@@ -65,6 +65,9 @@ export const soundsTypes = [
 ] as const;
 
 export async function loadAudio(file: string, useCache = true) {
+	if (ctx == null) {
+		ctx = new AudioContext();
+	}
 	if (useCache && cache.has(file)) {
 		return cache.get(file)!;
 	}
diff --git a/packages/frontend/src/widgets/WidgetJobQueue.vue b/packages/frontend/src/widgets/WidgetJobQueue.vue
index fa82997570..8c990e8e49 100644
--- a/packages/frontend/src/widgets/WidgetJobQueue.vue
+++ b/packages/frontend/src/widgets/WidgetJobQueue.vue
@@ -58,6 +58,7 @@ import { useStream } from '@/stream.js';
 import number from '@/filters/number.js';
 import * as sound from '@/scripts/sound.js';
 import { deepClone } from '@/scripts/clone.js';
+import { defaultStore } from '@/store.js';
 
 const name = 'jobQueue';
 
@@ -102,7 +103,9 @@ const prev = reactive({} as typeof current);
 let jammedAudioBuffer: AudioBuffer | null = $ref(null);
 let jammedSoundNodePlaying: boolean = $ref(false);
 
-sound.loadAudio('syuilo/queue-jammed').then(buf => jammedAudioBuffer = buf);
+if (defaultStore.state.sound_masterVolume) {
+	sound.loadAudio('syuilo/queue-jammed').then(buf => jammedAudioBuffer = buf);
+}
 
 for (const domain of ['inbox', 'deliver']) {
 	prev[domain] = deepClone(current[domain]);