blockenters commited on
Commit
8a43b69
·
1 Parent(s): 972e224
Files changed (4) hide show
  1. .gitignore +172 -0
  2. README.md +42 -5
  3. app.py +185 -0
  4. requirements.txt +5 -0
.gitignore ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ # Byte-compiled / optimized / DLL files
3
+ __pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ #Pipfile.lock
97
+
98
+ # UV
99
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ #uv.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ #poetry.lock
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ #pdm.lock
114
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
115
+ # in version control.
116
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
117
+ .pdm.toml
118
+ .pdm-python
119
+ .pdm-build/
120
+
121
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
122
+ __pypackages__/
123
+
124
+ # Celery stuff
125
+ celerybeat-schedule
126
+ celerybeat.pid
127
+
128
+ # SageMath parsed files
129
+ *.sage.py
130
+
131
+ # Environments
132
+ .env
133
+ .venv
134
+ env/
135
+ venv/
136
+ ENV/
137
+ env.bak/
138
+ venv.bak/
139
+
140
+ # Spyder project settings
141
+ .spyderproject
142
+ .spyproject
143
+
144
+ # Rope project settings
145
+ .ropeproject
146
+
147
+ # mkdocs documentation
148
+ /site
149
+
150
+ # mypy
151
+ .mypy_cache/
152
+ .dmypy.json
153
+ dmypy.json
154
+
155
+ # Pyre type checker
156
+ .pyre/
157
+
158
+ # pytype static type analyzer
159
+ .pytype/
160
+
161
+ # Cython debug symbols
162
+ cython_debug/
163
+
164
+ # PyCharm
165
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
166
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
167
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
168
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
169
+ #.idea/
170
+
171
+ # PyPI configuration file
172
+ .pypirc
README.md CHANGED
@@ -1,12 +1,49 @@
1
  ---
2
- title: Tts Kor
3
- emoji: 📚
4
- colorFrom: pink
5
- colorTo: pink
6
  sdk: streamlit
7
  sdk_version: 1.41.1
8
  app_file: app.py
9
  pinned: false
 
 
 
 
 
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: 한국어 음성 생성기 (Korean TTS)
3
+ emoji: 🎵
4
+ colorFrom: blue
5
+ colorTo: lightblue
6
  sdk: streamlit
7
  sdk_version: 1.41.1
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
+ python_version: 3.10
12
+ tags:
13
+ - text-to-speech
14
+ - korean
15
+ - audio
16
+ - streamlit
17
  ---
18
 
19
+ # 한국어 음성 생성기 (Korean TTS)
20
+
21
+ Meta AI의 MMS-TTS 모델을 활용한 한국어 음성 생성 웹 애플리케이션입니다.
22
+
23
+ ## 주요 기능
24
+
25
+ - 한국어 텍스트를 음성으로 변환
26
+ - 실시간 음성 생성 및 재생
27
+ - 생성된 음성 파일 다운로드 지원
28
+ - 직관적이고 사용하기 쉬운 인터페이스
29
+
30
+ ## 사용된 기술
31
+
32
+ - Facebook MMS-TTS 모델 (facebook/mms-tts-kor)
33
+ - Streamlit
34
+ - PyTorch
35
+ - Transformers
36
+
37
+ ## 사용 방법
38
+
39
+ 1. 텍스트 입력창에 변환하고 싶은 한글 텍스트를 입력합니다.
40
+ 2. "음성 생성하기" 버튼을 클릭합니다.
41
+ 3. 생성된 음성을 재생하거나 다운로드 받을 수 있습니다.
42
+
43
+ ## 라이선스
44
+
45
+ MIT License
46
+
47
+ ## 제작자
48
+
49
+ Blockenters
app.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # pip install transformers torch scipy uroman
2
+
3
+ import streamlit as st
4
+ from transformers import VitsModel, AutoTokenizer
5
+ import torch
6
+ import scipy.io
7
+ import os
8
+ import base64
9
+
10
+ # 페이지 설정
11
+ st.set_page_config(
12
+ page_title="한국어 TTS",
13
+ page_icon="🎵",
14
+ layout="centered"
15
+ )
16
+
17
+ # CSS 스타일 수정
18
+ st.markdown("""
19
+ <style>
20
+ .main-title {
21
+ font-size: 2.5rem;
22
+ color: #1E88E5;
23
+ margin-bottom: 2rem;
24
+ text-align: center;
25
+ }
26
+ .sub-header {
27
+ font-size: 1.5rem;
28
+ color: #424242;
29
+ margin-bottom: 1rem;
30
+ }
31
+ .highlight {
32
+ background-color: #E3F2FD;
33
+ padding: 1.2rem;
34
+ border-radius: 10px;
35
+ margin: 0.5rem 0;
36
+ }
37
+ .footer {
38
+ text-align: center;
39
+ color: #757575;
40
+ padding: 2rem 0;
41
+ }
42
+ .common-button {
43
+ background-color: #1E88E5;
44
+ color: white !important;
45
+ padding: 0.8rem 4rem;
46
+ font-size: 1.2rem;
47
+ border-radius: 25px;
48
+ width: 80%;
49
+ margin: 0 auto;
50
+ display: block;
51
+ border: none;
52
+ cursor: pointer;
53
+ }
54
+ .download-button {
55
+ background-color: #4CAF50 !important;
56
+ }
57
+ .stButton>button, .stDownloadButton>button {
58
+ background-color: #1E88E5;
59
+ color: white !important;
60
+ padding: 0.8rem 4rem;
61
+ font-size: 1.2rem;
62
+ border-radius: 25px;
63
+ width: 80%;
64
+ margin: 0 auto;
65
+ display: block;
66
+ }
67
+ .stButton>button span, .stDownloadButton>button span {
68
+ color: white !important;
69
+ }
70
+ .stDownloadButton>button {
71
+ background-color: #4CAF50 !important;
72
+ }
73
+ /* 텍스트 영역 레이블 여백 제거 */
74
+ .stTextArea label {
75
+ margin-top: 0 !important;
76
+ padding-top: 0 !important;
77
+ }
78
+ </style>
79
+ """, unsafe_allow_html=True)
80
+
81
+ # 헤더
82
+ st.markdown('<h1 class="main-title">🎵 한국어 음성 생성기</h1>', unsafe_allow_html=True)
83
+
84
+ # 소개 섹션
85
+ with st.container():
86
+ st.markdown('<p class="sub-header">✨ AI가 당신의 텍스트를 자연스러운 음성으로 변환해드립니다</p>', unsafe_allow_html=True)
87
+
88
+ # 모델 로드
89
+ @st.cache_resource
90
+ def load_model():
91
+ model = VitsModel.from_pretrained("facebook/mms-tts-kor")
92
+ tokenizer = AutoTokenizer.from_pretrained("facebook/mms-tts-kor")
93
+ return model, tokenizer
94
+
95
+ # 모델 로드
96
+ model, tokenizer = load_model()
97
+
98
+ # 메인 입력 섹션
99
+ st.markdown("""
100
+ <div class="highlight" style="padding: 0.8rem;">
101
+ <div style="color: #666; font-size: 0.9rem; margin-bottom: 0.3rem;">
102
+ ✏️ 아래 입력창에 변환할 텍스트를 입력하세요
103
+ </div>
104
+ """, unsafe_allow_html=True)
105
+ text = st.text_area(
106
+ "", # 레이블 제거
107
+ placeholder="예시) 안녕하세요. 텍스트를 음성으로 변환해드립니다.",
108
+ value="",
109
+ height=100
110
+ )
111
+ st.markdown('</div>', unsafe_allow_html=True)
112
+
113
+ def generate_audio(text):
114
+ inputs = tokenizer(text, return_tensors="pt")
115
+ with torch.no_grad():
116
+ output = model(**inputs).waveform
117
+ return output[0].numpy(), model.config.sampling_rate
118
+
119
+ def get_binary_file_downloader_html(bin_file, file_label='File'):
120
+ with open(bin_file, 'rb') as f:
121
+ data = f.read()
122
+ bin_str = base64.b64encode(data).decode()
123
+ href = f'<a href="data:application/octet-stream;base64,{bin_str}" download="{os.path.basename(bin_file)}" style="text-decoration:none;"><button class="common-button download-button">💾 다운로드</button></a>'
124
+ return href
125
+
126
+ # 사이드바에 사용방법 추가
127
+ with st.sidebar:
128
+ st.markdown("""
129
+ <div style="padding: 1rem;">
130
+ <h2 style="color: #1E88E5;">💡 사용 방법</h2>
131
+ <div class="highlight">
132
+ <b>간단 3단계로 음성을 생성하세요:</b><br><br>
133
+
134
+ 1️⃣ 텍스트 입력창에 원하는 한글 텍스트를 입력합니다.<br><br>
135
+
136
+ 2️⃣ '음성 생성하기' 버튼을 클릭합니다.<br><br>
137
+
138
+ 3️⃣ 생성된 음성을 재생하거나 다운로드 받으세요.<br>
139
+ </div>
140
+ </div>
141
+ """, unsafe_allow_html=True)
142
+
143
+ # 버튼 정렬 개선
144
+ st.markdown('<div style="display: flex; justify-content: center; margin: 2rem 0;">', unsafe_allow_html=True)
145
+ if st.button("🔊 음성 생성하기", key="generate"):
146
+ if text:
147
+ with st.spinner("🎵 음성을 생성하는 중..."):
148
+ # 음성 생성
149
+ audio_array, sample_rate = generate_audio(text)
150
+
151
+ # WAV 파일로 저장
152
+ filepath = "output.wav"
153
+ scipy.io.wavfile.write(filepath, rate=sample_rate, data=audio_array)
154
+
155
+ # 결과 컨테이너
156
+ result_container = st.container()
157
+ with result_container:
158
+ st.markdown('<div class="highlight" style="text-align: center;">', unsafe_allow_html=True)
159
+ st.success("✅ 음성 생성 완료! 플레이 버튼을 눌러 재생해보세요.")
160
+
161
+ # 오디오 재생 위젯 표시
162
+ st.audio(filepath)
163
+
164
+ # 다운로드 버튼
165
+ with open(filepath, "rb") as file:
166
+ st.download_button(
167
+ label="💾 음성 파일 다운로드",
168
+ data=file,
169
+ file_name="output.wav",
170
+ mime="audio/wav",
171
+ use_container_width=True
172
+ )
173
+ st.markdown('</div>', unsafe_allow_html=True)
174
+ else:
175
+ st.warning("⚠️ 텍스트를 입력해주세요!")
176
+ st.markdown('</div>', unsafe_allow_html=True)
177
+
178
+ # 푸터
179
+ st.markdown("""
180
+ <div class="footer">
181
+ <p>💖 Blockenters 💖</p>
182
+ </div>
183
+ """, unsafe_allow_html=True)
184
+
185
+
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit
2
+ transformers
3
+ torch
4
+ scipy
5
+ uroman