manifest.json
{
"manifest_version": 3,
"name": "Voice Typer Everywhere",
"version": "1.0",
"description": "어디서나 단축키로 구글 음성인식을 실행합니다.",
"permissions": [
"activeTab",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"commands": {
"toggle-voice-typing": {
"suggested_key": {
"default": "Ctrl+Shift+Y",
"mac": "MacCtrl+Shift+Y"
},
"description": "음성 인식 시작/종료"
}
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
background.js
// 사용자가 설정한 단축키 명령을 감지합니다.
chrome.commands.onCommand.addListener((command) => {
if (command === "toggle-voice-typing") {
// 현재 사용자가 보고 있는 활성화된 탭을 찾습니다.
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs[0]) {
// 활성화된 탭(content.js)으로 "음성인식을 토글하라"는 메시지를 보냅니다.
chrome.tabs.sendMessage(tabs[0].id, { action: "TOGGLE_VOICE" });
}
});
}
});
content.js
let recognition = null;
let isListening = false;
// 구글 음성 인식(Web Speech API) 초기화 함수
function initSpeechRecognition() {
// 브라우저 내장 구글 음성 인식 엔진 호출
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
console.error("이 브라우저는 구글 음성 인식 API를 지원하지 않습니다.");
return null;
}
const rec = new SpeechRecognition();
rec.continuous = true; // 말이 끊겨도 계속 인식하도록 설정
rec.interimResults = true; // 중간 인식 결과를 실시간으로 보여줌
rec.lang = 'ko-KR'; // 인식 언어를 한국어로 설정
// 음성이 인식되어 텍스트로 변환되었을 때 실행되는 이벤트
rec.onresult = (event) => {
let resultText = '';
for (let i = event.resultIndex; i < event.results.length; ++i) {
if (event.results[i].isFinal) {
resultText += event.results[i][0].transcript;
}
}
// 현재 사용자가 클릭해서 커서가 위치해 있는 텍스트 박스(입력창)를 찾습니다.
const activeElement = document.activeElement;
if (activeElement && resultText) {
// 일반적인 input창이나 textarea 창일 때 글자 주입
if (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA') {
activeElement.value += resultText + ' ';
}
// 구글 문서, 노션 등 contenteditable 속성을 쓰는 에디터일 때 글자 주입
else if (activeElement.isContentEditable) {
document.execCommand('insertText', false, resultText + ' ');
}
}
};
rec.onerror = (event) => {
console.error("음성 인식 오류 발생:", event.error);
isListening = false;
};
rec.onend = () => {
console.log("음성 인식 종료");
isListening = false;
};
return rec;
}
// background.js로부터 단축키 신호를 받았을 때의 처리
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "TOGGLE_VOICE") {
if (!recognition) {
recognition = initSpeechRecognition();
}
if (!recognition) return;
if (!isListening) {
recognition.start();
isListening = true;
console.log("🎤 음성 인식을 시작합니다... 말을 하세요.");
} else {
recognition.stop();
isListening = false;
console.log("🛑 음성 인식을 종료합니다.");
}
}
});