Skip to content

Commit 4b91079

Browse files
Merge pull request #1 from Unknown27s/main
Update README to reflect the addition of Document to Audio Converter …
2 parents 016a12a + 0455a4a commit 4b91079

File tree

3 files changed

+177
-1
lines changed

3 files changed

+177
-1
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<h1 align="center"> Python Beginner-Friendly Projects</h1>
22

33
<p align="center">
4-
A curated collection of <b>9 simple yet practical Python projects</b> — perfect for beginners learning loops, functions, logic, and file handling.
4+
A curated collection of <b>10 simple yet practical Python projects</b> — perfect for beginners learning loops, functions, logic, and file handling.
55
</p>
66

77
<p align="center">
@@ -35,6 +35,8 @@ You'll find small but useful programs — great for understanding **core syntax,
3535
| 7️⃣ |[To-Do List](To-Do-list/) | Manage daily tasks with add/remove features. |
3636
| 8️⃣ | 🗂️ [File Organizer](file-organizer/) | Automatically sort files into folders by extension. |
3737
| 9️⃣ | 🔢 [Unit Converter](unit-converter/) | Convert between common measurement units. |
38+
| 🔟 | 🔊 [Document to Audio Converter](document-to-audio-converter/) | Convert text from documents (`.docx`) into spoken audio. |
39+
3840

3941
---
4042

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Document to Audio Converter
2+
3+
A simple Python utility to convert text from Microsoft Word (`.docx`) documents into spoken audio. You can either listen to the audio directly or save it as a `.wav` file.
4+
5+
This script uses a simple, dialog-based interface for file selection and options.
6+
7+
## Features
8+
9+
- Reads text content from `.docx` files.
10+
- Converts the extracted text into speech.
11+
- **Option 1:** Speak the text aloud, paragraph by paragraph.
12+
- **Option 2:** Save the entire text as a single `.wav` audio file.
13+
- Handles missing dependencies and file-opening errors gracefully.
14+
15+
## Requirements
16+
17+
- Python 3.x
18+
- The following Python libraries:
19+
- `pyttsx3`
20+
- `python-docx`
21+
- `pypiwin32` (often required by `pyttsx3` on Windows)
22+
23+
## Installation
24+
25+
1. Clone this repository or download the `Pdftoaudio.py` script.
26+
27+
2. Install the required libraries using pip:
28+
29+
```bash
30+
pip install pyttsx3 python-docx pypiwin32
31+
```
32+
33+
## How to Use
34+
35+
1. Run the script from your terminal:
36+
37+
```bash
38+
python Pdftoaudio.py
39+
```
40+
41+
2. A file dialog will open. Select the `.docx` document you want to convert.
42+
43+
3. A dialog box will ask if you want to save the audio to a file.
44+
- Click **"Yes"** to open a "Save As" dialog and save the output as a `.wav` file.
45+
- Click **"No"** to have the script speak the document's text aloud directly.
46+
47+
4. Follow the on-screen prompts. Status messages will be printed to the console.
48+
49+
## Recent Code Improvements
50+
51+
The script was recently refactored to improve its quality, robustness, and maintainability. Key improvements include:
52+
53+
- **Dependency Management:** Imports are now organized at the top of the file. A startup check was added to ensure the `python-docx` library is installed, providing a user-friendly error message if it's missing.
54+
- **Robustness:**
55+
- The `tkinter` root window is now managed with a `contextmanager`, ensuring it is always properly destroyed.
56+
- A `try...finally` block was added around the text-to-speech engine logic to guarantee that `engine.stop()` is called, preventing the engine from hanging in case of an error.
57+
- **Code Structure & Readability:**
58+
- The `pyttsx3` engine setup was moved into its own helper function (`_initialize_engine`) to keep the main logic clean.
59+
- Type hints and docstrings were added to all functions, making the code self-documenting and easier to understand.
60+
61+
## Future Roadmap
62+
63+
This project is a great starting point, and there are several exciting features planned for the future to make it more powerful and user-friendly.
64+
65+
- **Support for More File Formats:**
66+
- Add support for reading text from **PDF files** (`.pdf`).
67+
- Add support for plain text files (`.txt`).
68+
69+
- **Full Graphical User Interface (GUI):**
70+
- Move away from simple dialog boxes to a complete GUI built with a framework like `tkinter` or `PyQt`.
71+
- The GUI would include features like a progress bar, play/pause/stop controls for live playback, and status displays.
72+
73+
- **Enhanced Audio Controls:**
74+
- Allow the user to select from available system voices.
75+
- Provide a slider or input box to adjust the speech rate and volume directly from the UI.
76+
77+
- **Cross-Platform Compatibility:**
78+
- Test and ensure the script works seamlessly on macOS and Linux. This may involve handling different text-to-speech engine backends.
79+
80+
- **Application Packaging:**
81+
- Package the application as a standalone executable (e.g., using `PyInstaller`) so that users can run it without needing to have Python or any libraries installed.
82+
83+
## Contributing
84+
85+
Contributions are welcome! If you'd like to help with any of the features on the roadmap or fix a bug, please feel free to fork the repository and submit a pull request.
86+
87+
## License
88+
89+
This project is licensed under the MIT License. See the `LICENSE` file for details.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import pyttsx3
2+
from tkinter import Tk, messagebox
3+
from tkinter.filedialog import askopenfilename, asksaveasfilename
4+
from contextlib import contextmanager
5+
6+
try:
7+
import docx
8+
except ImportError:
9+
# Use a dummy Tk instance for the error message if docx is not installed
10+
root = Tk()
11+
root.withdraw()
12+
messagebox.showerror("Dependency Error", "python-docx library not found.\nPlease install it with: pip install python-docx")
13+
root.destroy()
14+
exit()
15+
16+
@contextmanager
17+
def tkinter_root():
18+
"""Context manager for a withdrawn tkinter root window."""
19+
root = Tk()
20+
root.withdraw()
21+
try:
22+
yield root
23+
finally:
24+
root.destroy()
25+
26+
def _initialize_engine() -> pyttsx3.Engine:
27+
"""Initializes and configures the pyttsx3 engine."""
28+
engine = pyttsx3.init()
29+
rate = engine.getProperty("rate")
30+
engine.setProperty("rate", max(100, rate - 50)) # Slow down a bit more for clarity
31+
engine.setProperty("volume", 1.0)
32+
return engine
33+
34+
def docx_to_audio(docx_path: str):
35+
"""Reads a .docx file and converts its text to audio."""
36+
try:
37+
document = docx.Document(docx_path)
38+
except Exception as e:
39+
messagebox.showerror("Error", f"Failed to open Word document:\n{e}")
40+
return
41+
42+
paragraphs = [p.text for p in document.paragraphs if p.text.strip()]
43+
if not paragraphs:
44+
messagebox.showwarning("No text", "No text found in the Word document.")
45+
return
46+
47+
save_file = messagebox.askyesno("Save audio", "Save audio to a file instead of speaking?")
48+
engine = _initialize_engine()
49+
50+
try:
51+
if save_file:
52+
out_path = asksaveasfilename(title="Save audio as", defaultextension=".wav",
53+
filetypes=[("WAV files", "*.wav"), ("All files", "*.*")])
54+
if not out_path:
55+
messagebox.showinfo("Cancelled", "Save cancelled.")
56+
return
57+
text_to_speak = "\n\n".join(paragraphs)
58+
engine.save_to_file(text_to_speak, out_path)
59+
engine.runAndWait()
60+
messagebox.showinfo("Done", f"Audio saved to:\n{out_path}")
61+
else:
62+
# speak paragraph by paragraph to keep responsiveness
63+
for i, paragraph_text in enumerate(paragraphs, start=1):
64+
if not paragraph_text.strip():
65+
continue
66+
print(f"Speaking paragraph {i}/{len(paragraphs)}...")
67+
engine.say(paragraph_text)
68+
engine.runAndWait()
69+
except Exception as e:
70+
messagebox.showerror("Error", f"Failed during speech processing:\n{e}")
71+
finally:
72+
engine.stop()
73+
74+
def main():
75+
"""Main function to run the docx to audio converter."""
76+
with tkinter_root():
77+
docx_path = askopenfilename(title="Select Word Document", filetypes=[("Word Documents", "*.docx")])
78+
if not docx_path:
79+
print("No file selected. Exiting.")
80+
return
81+
82+
docx_to_audio(docx_path)
83+
84+
if __name__ == "__main__":
85+
main()

0 commit comments

Comments
 (0)