diff --git a/CHANGELOG.md b/CHANGELOG.md
index 838137d6b..ef3b99a34 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@
 
 ### Improvements
 - Misskey更新時にダイアログを表示するように
+- ジョブキューウィジェットに警報音を鳴らす設定を追加
 
 ### Bugfixes
 - ActivityPub: 長いユーザーの名前や自己紹介の対応
diff --git a/src/client/scripts/sound.ts b/src/client/scripts/sound.ts
index d3422bfff..c51fa8f21 100644
--- a/src/client/scripts/sound.ts
+++ b/src/client/scripts/sound.ts
@@ -2,6 +2,23 @@ import { ColdDeviceStorage } from '@client/store';
 
 const cache = new Map<string, HTMLAudioElement>();
 
+export function getAudio(file: string, useCache = true): HTMLAudioElement {
+	let audio: HTMLAudioElement;
+	if (useCache && cache.has(file)) {
+		audio = cache.get(file);
+	} else {
+		audio = new Audio(`/static-assets/client/sounds/${file}.mp3`);
+		if (useCache) cache.set(file, audio);
+	}
+	return audio;
+}
+
+export function setVolume(audio: HTMLAudioElement, volume: number): HTMLAudioElement {
+	const masterVolume = ColdDeviceStorage.get('sound_masterVolume');
+	audio.volume = masterVolume - ((1 - volume) * masterVolume);
+	return audio;
+}
+
 export function play(type: string) {
 	const sound = ColdDeviceStorage.get('sound_' + type as any);
 	if (sound.type == null) return;
@@ -12,13 +29,6 @@ export function playFile(file: string, volume: number) {
 	const masterVolume = ColdDeviceStorage.get('sound_masterVolume');
 	if (masterVolume === 0) return;
 
-	let audio: HTMLAudioElement;
-	if (cache.has(file)) {
-		audio = cache.get(file);
-	} else {
-		audio = new Audio(`/static-assets/client/sounds/${file}.mp3`);
-		cache.set(file, audio);
-	}
-	audio.volume = masterVolume - ((1 - volume) * masterVolume);
+	const audio = setVolume(getAudio(file), volume);
 	audio.play();
 }
diff --git a/src/client/widgets/job-queue.vue b/src/client/widgets/job-queue.vue
index beb80f7fa..327d8ede6 100644
--- a/src/client/widgets/job-queue.vue
+++ b/src/client/widgets/job-queue.vue
@@ -50,6 +50,7 @@ import { defineComponent, markRaw } from 'vue';
 import define from './define';
 import * as os from '@client/os';
 import number from '@client/filters/number';
+import * as sound from '@client/scripts/sound';
 
 const widget = define({
 	name: 'jobQueue',
@@ -58,6 +59,10 @@ const widget = define({
 			type: 'boolean',
 			default: false,
 		},
+		sound: {
+			type: 'boolean',
+			default: false,
+		},
 	})
 });
 
@@ -79,6 +84,7 @@ export default defineComponent({
 				delayed: 0,
 			},
 			prev: {},
+			sound: sound.setVolume(sound.getAudio('syuilo/queue-jammed'), 1)
 		};
 	},
 	created() {
@@ -107,6 +113,10 @@ export default defineComponent({
 				this[domain].active = stats[domain].active;
 				this[domain].waiting = stats[domain].waiting;
 				this[domain].delayed = stats[domain].delayed;
+
+				if (this[domain].waiting > 0 && this.props.sound && this.sound.paused) {
+					this.sound.play();
+				}
 			}
 		},