awacke1 commited on
Commit
b5b6b67
Β·
verified Β·
1 Parent(s): 0cbb5ef

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -0
app.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import base64
3
+ from gtts import gTTS
4
+ from io import BytesIO
5
+ import os
6
+ from PyPDF2 import PdfReader
7
+ import threading
8
+ import time
9
+ import hashlib
10
+ from datetime import datetime
11
+ import json
12
+
13
+ class AudioProcessor:
14
+ def __init__(self):
15
+ self.cache_dir = "audio_cache"
16
+ os.makedirs(self.cache_dir, exist_ok=True)
17
+ self.metadata = self._load_metadata()
18
+
19
+ def _load_metadata(self):
20
+ metadata_file = os.path.join(self.cache_dir, "metadata.json")
21
+ return json.load(open(metadata_file)) if os.path.exists(metadata_file) else {}
22
+
23
+ def create_audio(self, text, lang='en'):
24
+ cache_key = hashlib.md5(f"{text}:{lang}".encode()).hexdigest()
25
+ cache_path = os.path.join(self.cache_dir, f"{cache_key}.wav")
26
+
27
+ if cache_key in self.metadata and os.path.exists(cache_path):
28
+ return BytesIO(open(cache_path, 'rb').read())
29
+
30
+ sound_file = BytesIO()
31
+ tts = gTTS(text, lang=lang)
32
+ tts.write_to_fp(sound_file)
33
+
34
+ with open(cache_path, 'wb') as f:
35
+ f.write(sound_file.getvalue())
36
+
37
+ self.metadata[cache_key] = {
38
+ 'timestamp': datetime.now().isoformat(),
39
+ 'text_length': len(text),
40
+ 'lang': lang
41
+ }
42
+
43
+ sound_file.seek(0)
44
+ return sound_file
45
+
46
+ def get_download_link(bin_data, filename, size_mb=None):
47
+ b64 = base64.b64encode(bin_data).decode()
48
+ size_str = f"({size_mb:.1f} MB)" if size_mb else ""
49
+ return f'''
50
+ <div class="download-container">
51
+ <a href="data:application/octet-stream;base64,{b64}"
52
+ download="{filename}" class="download-link">πŸ“₯ {filename}</a>
53
+ <div class="file-info">{size_str}</div>
54
+ </div>
55
+ '''
56
+
57
+ def process_pdf(pdf_file, max_pages, language, audio_processor):
58
+ reader = PdfReader(pdf_file)
59
+ total_pages = min(len(reader.pages), max_pages)
60
+ texts, audios = [], {}
61
+
62
+ for i in range(total_pages):
63
+ text = reader.pages[i].extract_text()
64
+ texts.append(text)
65
+
66
+ # Process audio in background
67
+ threading.Thread(
68
+ target=lambda: audios.update({i: audio_processor.create_audio(text, language)})
69
+ ).start()
70
+
71
+ return texts, audios, total_pages
72
+
73
+ def main():
74
+ st.set_page_config(page_title="πŸ“š PDF to Audio 🎧", page_icon="πŸŽ‰", layout="wide")
75
+
76
+ # Apply styling
77
+ st.markdown("""
78
+ <style>
79
+ .download-link {
80
+ color: #1E90FF;
81
+ text-decoration: none;
82
+ padding: 8px 12px;
83
+ margin: 5px;
84
+ border: 1px solid #1E90FF;
85
+ border-radius: 5px;
86
+ display: inline-block;
87
+ transition: all 0.3s ease;
88
+ }
89
+ .download-link:hover {
90
+ background-color: #1E90FF;
91
+ color: white;
92
+ }
93
+ .file-info {
94
+ font-size: 0.8em;
95
+ color: gray;
96
+ margin-top: 4px;
97
+ }
98
+ </style>
99
+ """, unsafe_allow_html=True)
100
+
101
+ # Initialize processor
102
+ audio_processor = AudioProcessor()
103
+
104
+ # Sidebar settings
105
+ st.sidebar.title("πŸ“₯ Downloads & Settings")
106
+ language = st.sidebar.selectbox(
107
+ "Select Language",
108
+ options=['en', 'es', 'fr', 'de', 'it'],
109
+ format_func=lambda x: {'en': 'English', 'es': 'Spanish', 'fr': 'French',
110
+ 'de': 'German', 'it': 'Italian'}[x]
111
+ )
112
+
113
+ # Main interface
114
+ st.markdown("<h1>πŸ“š PDF to Audio Converter 🎧</h1>", unsafe_allow_html=True)
115
+
116
+ col1, col2 = st.columns(2)
117
+ with col1:
118
+ uploaded_file = st.file_uploader("Choose a PDF file", "pdf")
119
+ with col2:
120
+ max_pages = st.slider('Select pages to process', min_value=1, max_value=100, value=10)
121
+
122
+ if uploaded_file:
123
+ progress_bar = st.progress(0)
124
+ status = st.empty()
125
+
126
+ with st.spinner('Processing PDF...'):
127
+ texts, audios, total_pages = process_pdf(uploaded_file, max_pages, language, audio_processor)
128
+
129
+ for i, text in enumerate(texts):
130
+ with st.expander(f"Page {i+1}", expanded=i==0):
131
+ st.markdown(text)
132
+
133
+ # Wait for audio processing
134
+ while i not in audios:
135
+ time.sleep(0.1)
136
+ st.audio(audios[i], format='audio/wav')
137
+
138
+ # Add download link
139
+ size_mb = len(audios[i].getvalue()) / (1024 * 1024)
140
+ st.sidebar.markdown(
141
+ get_download_link(audios[i].getvalue(), f'page_{i+1}.wav', size_mb),
142
+ unsafe_allow_html=True
143
+ )
144
+
145
+ progress_bar.progress((i + 1) / total_pages)
146
+ status.text(f"Processing page {i+1}/{total_pages}")
147
+
148
+ st.success(f"βœ… Successfully processed {total_pages} pages!")
149
+
150
+ # Text to Audio section
151
+ st.markdown("### ✍️ Text to Audio")
152
+ prompt = st.text_area("Enter text to convert to audio", height=200)
153
+
154
+ if prompt:
155
+ with st.spinner('Converting text to audio...'):
156
+ sound_file = audio_processor.create_audio(prompt, language)
157
+ st.audio(sound_file, format='audio/wav')
158
+
159
+ size_mb = len(sound_file.getvalue()) / (1024 * 1024)
160
+ st.sidebar.markdown("### 🎡 Custom Audio")
161
+ st.sidebar.markdown(
162
+ get_download_link(sound_file.getvalue(), 'custom_text.wav', size_mb),
163
+ unsafe_allow_html=True
164
+ )
165
+
166
+ # Cache management
167
+ if st.sidebar.button("Clear Cache"):
168
+ for file in os.listdir(audio_processor.cache_dir):
169
+ os.remove(os.path.join(audio_processor.cache_dir, file))
170
+ st.sidebar.success("Cache cleared successfully!")
171
+
172
+ if __name__ == "__main__":
173
+ main()