들어가며
몇 달 전에 키보드를 누르면 오리가 "꽥" 하는 오리 키보드를 유튜브에서 봤다. 이걸 보니 너무 구현해보고 싶었다.
오리에게 목소리를!
소리가 나게 하는 두 가지 방법을 생각해 봤다. 하나는 키보드 자체에서 소리가 나게 하는 방법이고 두 번째는 컴퓨터에서 소리가 나게 하는 방법이다.
두 번째 방법을 구현한다면 키보드 종류에 상관없이 소프트웨어만 설치한다면 모든 키보드를 오리 키보드로 바꿀 수 있으므로 더 많은 사람들의 키보드에서 꽥 소리를 나게 할 수 있어서 범용성이 좋고, 무엇보다 컴퓨터에서 소리가 나게 하는 것은 키보드에서 소리가 나게 하는 것보단 만들기 쉬울 것이기에 구현성이 좋다고 보았다.
오리 소리를 구하자
다운로드 받고 mp3 확장자를 wav 확장자로 변환하고
garageband로 소리 앞 뒤를 다듬었다.
code: 키보드 입력 감지
-- 소리 파일 경로 설정
local soundPath = "/Users/frenny/Desktop/code/duck_sound_3.wav"
-- 볼륨 설정 (0.0부터 1.0 사이의 값)
local volumeLevel = 0.5 -- 원하는 볼륨 수준으로 설정
-- 모드 선택: "all" 또는 "specific"
local mode = "specific" -- 원하는 모드로 설정 ("all" 또는 "specific")
-- 특정 키 설정 (스페이스바와 엔터)
local specificKeys = {
space = true,
["return"] = true -- 'return'을 문자열로 감싸줍니다
}
-- 키 코드 매핑
local keyMap = {
space = hs.keycodes.map.space,
["return"] = hs.keycodes.map["return"]
}
-- 소리 객체를 미리 생성하여 재사용
local sound = hs.sound.getByFile(soundPath)
if not sound then
hs.notify.new({
title = "Hammerspoon",
informativeText = "소리 파일을 로드할 수 없습니다."
}):send()
end
sound:volume(volumeLevel)
-- 소리 재생 함수 정의
local function playSound()
if sound then
if sound:isPlaying() then
sound:stop()
end
sound:play()
end
end
-- 스페이스바 입력 감지 및 처리
local spaceKeyHandler = hs.eventtap.new({hs.eventtap.event.types.keyDown}, function(event)
local keyCode = event:getKeyCode()
if keyCode == hs.keycodes.map.space then
-- 소리 재생
playSound()
-- 이벤트를 통과시켜 스페이스바 입력이 정상적으로 처리되도록 함
return false
end
-- 다른 키에 대해서는 아무 작업도 하지 않고 이벤트를 통과시킴
return false
end)
-- 이벤트 핸들러 시작
spaceKeyHandler:start()
-- 설정 완료 알림
hs.notify.new({
title = "Hammerspoon",
informativeText = "키보드 소리 및 이벤트 스크립트가 활성화되었습니다."
}):send()
이렇게 코드를 짜니 잘 작동했지만, 2분가량 지나거나 한 문단 정도 타이핑하고 나면 소리가 더 이상 나지 않는 문제가 있었다. 도저히 원인을 찾을 수 없어서 어쩔 수 없이 다른 방법으로 구현해 보았다.
code: 우측 shift와 연계
-- foundation_remapping 모듈 로드
local FRemap = require('foundation_remapping')
-- 글로벌 리매퍼 생성 (모든 장치에 적용)
local remapper = FRemap.new()
-- 우측 Shift 키를 F19로 리매핑
remapper:remap('rshift', 'f19')
-- 리매핑 활성화
remapper:register()
-- 입력 소스 식별자 설정 (확인한 값으로 변경하세요)
local englishInputSource = "com.apple.keylayout.ABC" -- 영어 입력 소스 ID
-- local koreanInputSource = "com.apple.inputmethod.Korean.2SetKorean" -- 한국어 입력 소스 ID (사용하지 않음)
-- 입력 소스 전환 함수
local function setInputSource(sourceID)
print("Changing input source to: " .. sourceID)
hs.keycodes.currentSourceID(sourceID)
end
-- ESC 키 전송 함수
local function sendEscape()
hs.eventtap.keyStroke({}, "escape")
end
-- 소리 파일 경로 설정
local soundPath = "/Users/frenny/Desktop/code/duck_sound_3.wav" -- 본인 경로에 맞게 설정할 것
-- 볼륨 설정 (0.0부터 1.0 사이의 값)
local volumeLevel = 0.5 -- 원하는 볼륨 수준으로 설정
-- 소리 객체를 미리 생성하여 재사용
local sound = hs.sound.getByFile(soundPath)
if not sound then
hs.notify.new({
title = "Hammerspoon",
informativeText = "소리 파일을 로드할 수 없습니다."
}):send()
end
sound:volume(volumeLevel)
-- 소리 재생 함수 정의
local function playSound()
if sound then
if sound:isPlaying() then
sound:stop()
end
sound:play()
end
end
-- F19 키 핸들러 설정
hs.hotkey.bind({}, "f19", function()
setInputSource(englishInputSource)
sendEscape()
playSound()
end)
마치며
모든 키보드 키에 반응하는 버전과, 스페이스바와 엔터키에만 반응하는 버전을 만들었는데, 원리가 어떤 키가 입력되었는지 체크하는 것인데 알 수 없는 이유로 키 입력 신호를 hammerspoon에서 받을 수 없게 되는 문제가 생겼다. 문득 우측 shift키를 f19로 바꾸고 입력 시 esc와 영어 전환이 되게 해 둔 것이 생각났다. 키 입력을 체크하지 않고, f19를 누르면 오리소리가 나게 하니 잘 작동했다. 이제 vim에서 비주얼 모드로 넘어갈 때마다 오리 소리가 나게 되었다. 원래 계획했던 것과 다르게 구현하여 조금 아쉽긴 하지만, 적절한 빈도로 오리소리가 나는 것이기도 하고, 내 컴퓨터를 사용한 사람이 우측 shift를 눌렀을 때 깜짝 놀랄 모습을 상상하면 너무 만족스럽다. 생각대로 되진 않았지만, 생각보다 재밌는 기능이 된 것 같다.(꽥)
'혼자놀기' 카테고리의 다른 글
캐릭터 말풍선 구현하기 for obsidian & website (5) | 2025.03.15 |
---|---|
MacOS 유튜브 차단하기 (0) | 2024.12.12 |
MacOS 한영 전환 Hammerspoon을 이용한 딜레이 해결 (0) | 2024.11.23 |
100r Orca 문법 정리 (0) | 2024.11.18 |
hammerspoon으로 우측 shift를 ESC + 영어 입력 (0) | 2024.11.06 |