๐ŸŽต ๊ฐ์ •์„ ์†Œ๋ฆฌ๋กœ ๋ฐ”๊พธ๋‹ค โ€“ Sound of Mood

ย 

ย 


๐Ÿ’ก ์˜ค๋Š˜์˜ ์‹คํ—˜ ์ฃผ์ œ

๊ฐ์ •์—๋Š” ์ƒ‰๋„ ์žˆ์ง€๋งŒ, ๋ฆฌ๋“ฌ๋„ ์žˆ๋‹ค.
๊ธฐ์จ์€ ๋น ๋ฅด๊ณ  ๋ฐ์€ ์Œ์œผ๋กœ, ์Šฌํ””์€ ๋А๋ฆฌ๊ณ  ๋‚ฎ์€ ์Œ์œผ๋กœ ์šธ๋ฆฐ๋‹ค.
์˜ค๋Š˜์˜ ๋ชฉํ‘œ๋Š” AI ๊ฐ์ •์„ โ€˜์†Œ๋ฆฌ ๋ฐ์ดํ„ฐโ€™๋กœ ๋ณ€ํ™˜ํ•ด ์Œ์•…์ฒ˜๋Ÿผ ๋“ค๋ ค์ฃผ๋Š” ์ฝ”๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.


๐Ÿงฐ ์‚ฌ์šฉํ•œ ๋„๊ตฌ

๋„๊ตฌ ์—ญํ•  ์„ค๋ช…
๐ŸŽง numpy ์‚ฌ์ธํŒŒ ์Œ ์ƒ์„ฑ ๊ฐ์ • ์ ์ˆ˜๋ฅผ ์ฃผํŒŒ์ˆ˜(frequency)๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ŒํŒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
๐ŸŽ›๏ธ pydub ์˜ค๋””์˜ค ํŒŒ์ผ ์ƒ์„ฑ NumPy๋กœ ๋งŒ๋“  ์Œ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์ œ .wav ํŒŒ์ผ๋กœ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์žฌ์ƒํ•ฉ๋‹ˆ๋‹ค.
๐Ÿง  openai ๊ฐ์ • ๋ถ„์„ ์ž…๋ ฅ๋œ ๋ฌธ์žฅ์˜ ๊ฐ์ • ๊ฐ•๋„(0~1)๋ฅผ ์ถ”์ถœํ•˜์—ฌ ์†Œ๋ฆฌ ๋งคํ•‘์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ป VS Code ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์‹คํ—˜ ์ „์šฉ ํŽธ์ง‘๊ธฐ. ์Œ์„ฑ ํŒŒ์ผ์€ ๊ฐ™์€ ํด๋”์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

๐Ÿงฉ 1๏ธโƒฃ ํ™˜๊ฒฝ ์„ธํŒ…

pip install numpy pydub openai

โš ๏ธ pydub์€ ๋‚ด๋ถ€์ ์œผ๋กœ ffmpeg๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ,
์‹œ์Šคํ…œ์— ffmpeg๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

# macOS
brew install ffmpeg

# Windows (choco ์‚ฌ์šฉ)
choco install ffmpeg

๐Ÿง  2๏ธโƒฃ ๊ฐ์ • ์ ์ˆ˜๋ฅผ ๋ฐ›์•„์˜ค๊ธฐ

OpenAI API๋ฅผ ์‚ฌ์šฉํ•ด ๋ฌธ์žฅ์˜ ๊ฐ์ •์„ ์ˆ˜์น˜ํ™”ํ•ฉ๋‹ˆ๋‹ค.

import openai

openai.api_key = "YOUR_API_KEY"

def analyze_emotion(sentence):
    prompt = f"'{sentence}' ๋ฌธ์žฅ์˜ ๊ฐ์ •์„ 0~1 ์‚ฌ์ด์˜ ์ˆ˜์น˜๋กœ ํ‘œํ˜„ํ•ด์ค˜. 1์€ ๋งค์šฐ ๊ธ์ •, 0์€ ๋งค์šฐ ๋ถ€์ •."
    res = openai.ChatCompletion.create(
        model="gpt-4-turbo",
        messages=[{"role":"user","content":prompt}]
    )
    return float(res.choices[0].message.content.strip())

score = analyze_emotion("์˜ค๋Š˜์€ ํ–‡์‚ด์ด ๋”ฐ๋œปํ•˜๊ณ  ๋งˆ์Œ์ด ๊ฐ€๋ฒผ์›Œ์š”.")
print("๊ฐ์ • ์ ์ˆ˜:", score)

์ถœ๋ ฅ ์˜ˆ์‹œ:
๊ฐ์ • ์ ์ˆ˜: 0.87
โ†’ ๊ฐ์ •์ด ๋ฐ๊ณ  ๊ธ์ •์ ์ผ์ˆ˜๋ก ๋†’์€ ์ˆ˜์น˜๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.


๐ŸŽต 3๏ธโƒฃ ๊ฐ์ • ์ ์ˆ˜๋ฅผ ์†Œ๋ฆฌ๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ

๊ฐ์ • ์ ์ˆ˜์— ๋”ฐ๋ผ ์ฃผํŒŒ์ˆ˜๋ฅผ ๋ฐ”๊ฟ”๋ด…์‹œ๋‹ค.
๊ธฐ๋ณธ ์Œ์€ 440Hz(A4), ๊ฐ์ • ์ ์ˆ˜๋กœ ์Œ ๋†’์ด๋ฅผ ์กฐ์ ˆํ•ฉ๋‹ˆ๋‹ค.

import numpy as np
from pydub import AudioSegment
from pydub.playback import play

def emotion_to_tone(score):
    duration = 1500  # ms
    base_freq = 440  # Hz
    freq = base_freq + (score - 0.5) * 400  # ๊ฐ์ •์— ๋”ฐ๋ผ ๋†’๋‚ฎ์ด ์กฐ์ ˆ
    volume = -10 + (score * 10)  # dB ์กฐ์ •

    sample_rate = 44100
    t = np.linspace(0, duration / 1000, int(sample_rate * duration / 1000), False)
    wave = np.sin(freq * t * 2 * np.pi)
    audio = (wave * 32767).astype(np.int16)
    sound = AudioSegment(audio.tobytes(), frame_rate=sample_rate, sample_width=2, channels=1)
    sound = sound + volume
    return sound

tone = emotion_to_tone(0.87)
play(tone)

๐Ÿ”Š ์ถœ๋ ฅ ๊ฒฐ๊ณผ: ๋ฐ๊ณ  ๋†’์€ ์Œ์ด ์•ฝ 1.5์ดˆ ๋™์•ˆ ์žฌ์ƒ๋ฉ๋‹ˆ๋‹ค.
๊ฐ์ •์ด ์–ด๋‘์›Œ์งˆ์ˆ˜๋ก ์Œ์€ ๋‚ฎ์•„์ง€๊ณ  ๊ธธ์ด๋Š” ์งง์•„์ง‘๋‹ˆ๋‹ค.


๐ŸŽผ 4๏ธโƒฃ ๊ฐ์ • ์ผ๊ธฐ๋ฅผ ์†Œ๋ฆฌ๋กœ ๋‚จ๊ธฐ๊ธฐ

ํ•˜๋ฃจ์˜ ๊ฐ์ • ๊ธฐ๋ก์„ ์—ฌ๋Ÿฌ ๋ฌธ์žฅ์œผ๋กœ ์ž…๋ ฅํ•˜๋ฉด,
๊ฐ์ •์˜ ํ๋ฆ„์„ ์Œ ๋†’์ด๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

sentences = [
    "์•„์นจ ๊ณต๊ธฐ๊ฐ€ ์ƒ์พŒํ–ˆ๋‹ค.",
    "ํšŒ์˜๋Š” ์กฐ๊ธˆ ์ง€๋ฃจํ–ˆ์ง€๋งŒ ๊ดœ์ฐฎ์•˜๋‹ค.",
    "์ €๋…์—” ๊ฐ€์กฑ๊ณผ ์›ƒ์œผ๋ฉฐ ์‹์‚ฌํ–ˆ๋‹ค."
]

track = AudioSegment.silent(duration=0)

for s in sentences:
    score = analyze_emotion(s)
    sound = emotion_to_tone(score)
    track += sound

track.export("mood_sound.wav", format="wav")
print("๐ŸŽถ ๊ฐ์ • ์ผ๊ธฐ ์‚ฌ์šด๋“œ ํŒŒ์ผ ์ €์žฅ ์™„๋ฃŒ!")

๐Ÿ’พ ๊ฒฐ๊ณผ: mood_sound.wav
โ€“ ํ•˜๋ฃจ์˜ ๊ฐ์ •์ด ์—ฐ์†๋œ ์Œ์œผ๋กœ ๋ณ€ํ™˜๋œ ํŒŒ์ผ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.


๐ŸŽง 5๏ธโƒฃ ์‹คํ—˜ ํ›„๊ธฐ

AI๋Š” ๊ฐ์ •์„ ์ฝ๊ณ , ํŒŒ์ด์ฌ์€ ๊ทธ๊ฒƒ์„ ๋“ค๋ ค์คฌ๋‹ค.
๊ธฐ์จ์€ ๋ง‘์€ ๋„(Do), ์Šฌํ””์€ ๋‚ฎ์€ ์†”(Sol)์ฒ˜๋Ÿผ ์šธ๋ฆฐ๋‹ค.
์ด๊ฑด ๋‹จ์ˆœํ•œ ์‚ฌ์šด๋“œ ์‹คํ—˜์ด ์•„๋‹ˆ๋ผ,
๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ์ •์˜ ์–ธ์–ด๋ฅผ ์–ป์€ ์ˆœ๊ฐ„์ด์—ˆ๋‹ค.

“์Œ์•…์€ ๊ฐ์ •์„ ๋ฒˆ์—ญํ•œ ๋ฐ์ดํ„ฐ๋‹ค.
AI๋Š” ๊ทธ ๋ฒˆ์—ญ๊ฐ€์ผ ๋ฟ, ๊ฐ์ •์˜ ์ฃผ์ธ์€ ์—ฌ์ „ํžˆ ์ธ๊ฐ„์ด๋‹ค.”

๊ธฐ์ˆ ์ด ์ธ๊ฐ„์˜ ๊ฐ์ •์„ ๋Œ€์ฒดํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ,
๊ทธ ๊ฐ์ •์„ โ€˜์ƒˆ๋กœ์šด ํ˜•์‹โ€™์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋•๋Š” ๊ฒƒ โ€”
์ด๊ฒŒ ๋ชฝ๋ธ”์ด ์ถ”๊ตฌํ•˜๋Š” ๋ฐ”์ด๋ธŒ์ฝ”๋”ฉ์ด๋‹ค.


๐Ÿช„ ๋‹ค์Œ ์‹คํ—˜ ์˜ˆ๊ณ 

โ€œ๊ฐ์ •์˜ ๋ƒ„์ƒˆ โ€“ ํ–ฅ์œผ๋กœ ๊ธฐ์–ตํ•˜๋Š” ์ฝ”๋“œโ€
๋‹ค์Œ ์‹คํ—˜์—์„œ๋Š” ํ…์ŠคํŠธ ๊ฐ์ • โ†’ ํ–ฅ ๋ฐ์ดํ„ฐ โ†’ ๋””์ง€ํ„ธ ์„ผ์„œ๋กœ ์ด์–ด์ง€๋Š”
ใ€ˆ๋ฐ”์ด๋ธŒ์ฝ”๋”ฉ #4: Scent of Codeใ€‰ ๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ”– ํ•ด์‹œํƒœ๊ทธ

#๋ชฝ๋ธ” #๋ฐ”์ด๋ธŒ์ฝ”๋”ฉ #AI์Œ์•…์‹คํ—˜ #SoundOfMood #๊ฐ์ •์‚ฌ์šด๋“œ #ํŒŒ์ด์ฌ์‹คํ—˜ #pydub #numpy #openai #AI์ฐฝ์ž‘

๋Œ“๊ธ€ ๋‚จ๊ธฐ๊ธฐ