소개
영어/ 중국어 단어장을 효율적으로 공부하기 위해 소리 및 자막이 나오는 영상으로 만들어보기
진행 방법
엑셀 시트에 단어장이나 회화 문장을 준비
A열 영어, B열 한국어 C열 중국어, 1행은 언어 표시
2행부터 실제 단어(문장)을 입력, 샘플로 10개 정도
엑셀 파일명은 voca1000.xlsx로 하고 파이썬 코드와 동일 폴더에 저장
Tip: 사용한 프롬프트 전문을 꼭 포함하고, 내용을 짧게 소개해 주세요.
커서 설치 및 입코딩 작업 준비
커서 설치(스터디 가이드 자료 참고)
익스텐션 설치 : Python, Excel viewer
파이썬 작업폴더 만들기 : 예시 Python
엑셀 단어장 폴더 만들기 : 예시 Edge-word
파이썬 파일 만들기 : 예시 Voca_app.py
Tip: 활용 이미지나 캡처 화면을 꼭 남겨주세요.
커서 프롬프트를 아래와 같이 입력
엑셀 단어를 화면으로 표시하면서 동시에 음성으로 읽어 주는 코드 작성 엑셀 파일명은 voca1000.xlsx. 현재폴더, 헤더 있고, A열 영어, B열 한국어 C열 중국어 라이브러리 : 음성은 edgeTTS, 화면은 tkinter프롬프트에 대한 커서 응답 내용
커서에서 84줄 코드를 작성했고
필요한 라이브러리 설치를 위한 requirements.txt 제공
설치방법 우측에 보이는 Run을 클릭하면 라이브러리 파일이 자동 설치됨
커서 화면 중앙 하단 터미날에 3개의 라이브러리 설치 결과가 보임
파이썬 프로그램을 실행 버튼을 클릭하고 3초 정도 기다리면 단어장 출현
실제 코드 내용(84줄) 1차
import tkinter as tk
from tkinter import ttk
import pandas as pd
import edge_tts
import asyncio
import os
class VocaApp:
def __init__(self, root):
self.root = root
self.root.title("단어 학습기")
self.root.geometry("600x400")
# 엑셀 파일 읽기
self.df = pd.read_excel('voca1000.xlsx')
self.current_index = 0
# UI 구성
self.create_widgets()
# 첫 번째 단어 표시
self.show_word()
def create_widgets(self):
# 영어 단어 표시
self.eng_label = ttk.Label(self.root, text="", font=("Arial", 24))
self.eng_label.pack(pady=20)
# 한국어 의미 표시
self.kor_label = ttk.Label(self.root, text="", font=("Arial", 18))
self.kor_label.pack(pady=10)
# 중국어 의미 표시
self.chi_label = ttk.Label(self.root, text="", font=("Arial", 18))
self.chi_label.pack(pady=10)
# 버튼 프레임
button_frame = ttk.Frame(self.root)
button_frame.pack(pady=20)
# 이전 버튼
self.prev_btn = ttk.Button(button_frame, text="이전", command=self.prev_word)
self.prev_btn.pack(side=tk.LEFT, padx=5)
# 다음 버튼
self.next_btn = ttk.Button(button_frame, text="다음", command=self.next_word)
self.next_btn.pack(side=tk.LEFT, padx=5)
# 발음 버튼
self.speak_btn = ttk.Button(button_frame, text="발음", command=self.speak_word)
self.speak_btn.pack(side=tk.LEFT, padx=5)
def show_word(self):
if 0 <= self.current_index < len(self.df):
self.eng_label.config(text=self.df.iloc[self.current_index, 0])
self.kor_label.config(text=self.df.iloc[self.current_index, 1])
self.chi_label.config(text=self.df.iloc[self.current_index, 2])
def next_word(self):
if self.current_index < len(self.df) - 1:
self.current_index += 1
self.show_word()
def prev_word(self):
if self.current_index > 0:
self.current_index -= 1
self.show_word()
async def speak(self, text):
communicate = edge_tts.Communicate(text, 'en-US-JennyNeural')
await communicate.save("temp.mp3")
os.system("afplay temp.mp3")
os.remove("temp.mp3")
def speak_word(self):
if 0 <= self.current_index < len(self.df):
word = self.df.iloc[self.current_index, 0]
asyncio.run(self.speak(word))
if __name__ == "__main__":
root = tk.Tk()
app = VocaApp(root)
root.mainloop()
결과와 배운 점
배운 점과 나만의 꿀팁을 알려주세요.
과정 중에 어떤 시행착오를 겪었나요?
단어장을 만들때 어떻게 보여질지에 대한 구체적인 내용이 필요
예를 들면 한글, 영어 단어를 순서대로 자막 표시
자막을 표시하고 0.1초 후에 음성 재생
음성 재생 완료후 다음 단어 표시
세트가 완료되면 0.5초후 다음 단어 표시
10번 정도의 수정 및 보완을 통해 업그레이드 버젼
수정보완 단어장 이미지(2차)
(수정 보완된 코드 2차(256줄)
import tkinter as tk
from tkinter import ttk
import pandas as pd
import edge_tts
import asyncio
import os
import time
from concurrent.futures import ThreadPoolExecutor
class VocaApp:
def __init__(self, root):
self.root = root
self.root.title("단어 학습기")
self.root.geometry("800x600")
self.root.configure(bg='#2C3E50') # 어두운 배경색
# 엑셀 파일 읽기
self.df = pd.read_excel('voca1000.xlsx')
self.current_index = 0
self.is_playing = False
self.executor = ThreadPoolExecutor(max_workers=1)
# 재생 속도 설정
self.playback_speed = 1.8
# UI 구성
self.create_widgets()
# 첫 번째 단어 표시
self.show_word()
def create_widgets(self):
# 메인 프레임
main_frame = ttk.Frame(self.root)
main_frame.pack(expand=True, fill='both', padx=20, pady=20)
# 속도 조절 프레임
speed_frame = ttk.Frame(main_frame)
speed_frame.pack(pady=10)
# 속도 레이블
speed_label = tk.Label(
speed_frame,
text="재생 속도:",
font=("Arial", 12),
bg='#2C3E50',
fg='white'
)
speed_label.pack(side=tk.LEFT, padx=5)
# 속도 표시 레이블 (먼저 생성)
self.speed_value_label = tk.Label(
speed_frame,
text="1.8x",
font=("Arial", 12),
bg='#2C3E50',
fg='white'
)
self.speed_value_label.pack(side=tk.LEFT, padx=5)
# 속도 슬라이더
self.speed_scale = ttk.Scale(
speed_frame,
from_=0.5,
to=4.0,
orient=tk.HORIZONTAL,
length=200,
command=self.update_speed
)
self.speed_scale.set(1.8)
self.speed_scale.pack(side=tk.LEFT, padx=5)
# 한국어 의미 표시
self.kor_label = tk.Label(
main_frame,
text="",
font=("Arial", 36, "bold"),
bg='#2C3E50',
fg='white',
pady=20
)
self.kor_label.pack(pady=20)
# 영어 단어 표시
self.eng_label = tk.Label(
main_frame,
text="",
font=("Arial", 28),
bg='#2C3E50',
fg='#3498DB',
pady=20
)
self.eng_label.pack(pady=20)
# 중국어 의미 표시
self.chi_label = tk.Label(
main_frame,
text="",
font=("Arial", 28),
bg='#2C3E50',
fg='#E74C3C',
pady=20
)
self.chi_label.pack(pady=20)
# 버튼 프레임
button_frame = ttk.Frame(main_frame)
button_frame.pack(pady=30)
# 버튼 스타일 설정
style = ttk.Style()
style.configure('Custom.TButton',
font=('Arial', 28, 'bold'),
padding=15)
# 버튼 크기 설정
button_width = 6
# 이전 버튼
self.prev_btn = ttk.Button(
button_frame,
text="이전",
command=self.prev_word,
style='Custom.TButton',
width=button_width
)
self.prev_btn.pack(side=tk.LEFT, padx=10)
# 다음 버튼
self.next_btn = ttk.Button(
button_frame,
text="다음",
command=self.next_word,
style='Custom.TButton',
width=button_width
)
self.next_btn.pack(side=tk.LEFT, padx=10)
# 발음 버튼
self.speak_btn = ttk.Button(
button_frame,
text="발음",
command=self.speak_word,
style='Custom.TButton',
width=button_width
)
self.speak_btn.pack(side=tk.LEFT, padx=10)
# 자동 재생 버튼
self.auto_btn = ttk.Button(
button_frame,
text="자동 재생",
command=self.toggle_auto_play,
style='Custom.TButton',
width=button_width
)
self.auto_btn.pack(side=tk.LEFT, padx=10)
def update_speed(self, value):
self.playback_speed = float(value)
self.speed_value_label.config(text=f"{self.playback_speed:.1f}x")
def show_word(self):
if 0 <= self.current_index < len(self.df):
self.kor_label.config(text=self.df.iloc[self.current_index, 1])
self.eng_label.config(text=self.df.iloc[self.current_index, 0])
self.chi_label.config(text=self.df.iloc[self.current_index, 2])
def next_word(self):
if self.current_index < len(self.df) - 1:
self.current_index += 1
self.show_word()
def prev_word(self):
if self.current_index > 0:
self.current_index -= 1
self.show_word()
async def speak(self, text, voice='en-US-JennyNeural'):
try:
communicate = edge_tts.Communicate(text, voice)
await communicate.save("temp.mp3")
# 음성 재생 속도 조절
if self.playback_speed != 1.0:
# ffmpeg를 사용하여 음성 속도 조절
os.system(f"/opt/homebrew/bin/ffmpeg -i temp.mp3 -filter:a atempo={self.playback_speed} -y temp_speed.mp3")
os.system("afplay temp_speed.mp3")
os.remove("temp_speed.mp3")
else:
os.system("afplay temp.mp3")
os.remove("temp.mp3")
except Exception as e:
print(f"음성 재생 중 오류 발생: {e}")
def speak_word(self):
if 0 <= self.current_index < len(self.df):
word = self.df.iloc[self.current_index, 0]
asyncio.run(self.speak(word))
def toggle_auto_play(self):
self.is_playing = not self.is_playing
if self.is_playing:
self.auto_btn.config(text="정지")
self.executor.submit(self.run_auto_play)
else:
self.auto_btn.config(text="자동 재생")
def run_auto_play(self):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(self.auto_play_sequence())
loop.close()
async def auto_play_sequence(self):
while self.is_playing and self.current_index < len(self.df):
try:
# 현재 단어 표시
self.root.after(0, self.show_word)
# 대기 시간을 재생 속도에 맞게 조절
wait_time = 0.1 / self.playback_speed
await asyncio.sleep(wait_time)
# 한국어 발음
kor_word = self.df.iloc[self.current_index, 1]
await self.speak(kor_word, 'ko-KR-SunHiNeural')
# 대기 시간을 재생 속도에 맞게 조절
wait_time = 0.5 / self.playback_speed
await asyncio.sleep(wait_time)
# 영어 단어 발음
eng_word = self.df.iloc[self.current_index, 0]
await self.speak(eng_word, 'en-US-JennyNeural')
# 다음 단어로 이동
if self.current_index < len(self.df) - 1:
self.current_index += 1
# 대기 시간을 재생 속도에 맞게 조절
wait_time = 0.5 / self.playback_speed
await asyncio.sleep(wait_time)
else:
self.is_playing = False
self.root.after(0, lambda: self.auto_btn.config(text="자동 재생"))
except Exception as e:
print(f"자동 재생 중 오류 발생: {e}")
self.is_playing = False
self.root.after(0, lambda: self.auto_btn.config(text="자동 재생"))
break
if __name__ == "__main__":
root = tk.Tk()
app = VocaApp(root)
root.mainloop()
도움 받은 글 (옵션)
참고한 지피터스 글이나 외부 사례를 알려주세요.
(내용 입력)