Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support: txt file support added #16

Merged
merged 2 commits into from
Oct 15, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pip install audiobook

```python
from audiobook import AudioBook
ab = AudioBook() # argument: Speech-Speed="slow/normal/fast"
ab = AudioBook(speed="normal") # argument: Speech-Speed="slow/normal/fast"

ab.save_audio(file_path, password=None) # save audio file
ab.read_book(file_path, password=None) # listen to the book
Expand Down Expand Up @@ -71,15 +71,18 @@ sudo apt update && sudo apt install espeak ffmpeg libespeak1

## Project status

## V1.0.0
This project is currently in development. Any contributions are welcome.

## Changelog

**V2.0.0**

- [x] Save Audio Book locally
- [x] Listen to the book
- [x] Speech-speed control
- [x] Read password protected PDF
- [x] Create json file for the book

## Upcoming Features
- [x] Read password-protected PDF
- [x] Create JSON file for the book
- [ ] Change the voice of the narrator

- [ ] Support more extensions

Expand Down
148 changes: 85 additions & 63 deletions audiobook/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,46 @@
"fast": 200}


def speak_text(engine, text, print=False):
if print:
def speak_text(engine, text, display=True):
if display:
print(text)
engine.say(text)
engine.runAndWait()


class AudioBook:
"""
AudioBook class

methods:
file_check: checks if file exists
pdf_to_json: converts pdf to json format
create_json_book: Creates json book from input file by calling respective method
save_audio: saves audio files in folder
read_book: reads the book

sample usage:
ab = AudioBook(speed="normal")
ab.read_book(file_path, password="abcd")
"""

def __init__(self, speed="normal"):
self.engine = pyttsx3.init()
self.engine.setProperty("rate", speed_dict[speed])

def create_json_book(self, pdf_file_path, password=None):

if not os.path.exists(pdf_file_path):

def file_check(self, file_path):
"""
checks file format and if file exists
"""
if not os.path.exists(file_path):
raise FileNotFoundError("File not found!")

if not pdf_file_path.endswith(".pdf"):
raise ValueError("File must be a pdf!")


def pdf_to_json(self, input_file_path, password=None):
"""
Converts pdf to json format
"""
book_dict = {}
with open(pdf_file_path, "rb") as fp:
with open(input_file_path, "rb") as fp:
pdfReader = PyPDF2.PdfFileReader(fp)
if pdfReader.isEncrypted:
logging.info("File is encrypted, trying to decrypt...")
Expand All @@ -45,15 +63,28 @@ def create_json_book(self, pdf_file_path, password=None):
book_dict[num] = text
return book_dict, pages

def save_audio(self, pdf_file_path, password=None):
if not os.path.exists(pdf_file_path):
raise FileNotFoundError("File not found!")
def txt_to_json(self, input_file_path):
book_dict = {}
with open(input_file_path, "r") as fp:
file_data = fp.read()

if not pdf_file_path.endswith(".pdf"):
raise ValueError("File must be a pdf!")
# split text into pages of 2000 characters
for i in range(0, len(file_data), 2000):
book_dict[i] = file_data[i:i+2000]
return book_dict, len(book_dict)

with open(pdf_file_path, "rb") as fp:
basename = os.path.basename(pdf_file_path).split(".")[0]
def create_json_book(self, input_file_path, password=None):
self.file_check(input_file_path)
if input_file_path.endswith(".pdf"):
book_dict, pages = self.pdf_to_json(input_file_path, password)
elif input_file_path.endswith(".txt"):
book_dict, pages = self.txt_to_json(input_file_path)
return book_dict, pages

def save_audio(self, input_file_path, password=None):
self.file_check(input_file_path)
with open(input_file_path, "rb") as fp:
basename = os.path.basename(input_file_path).split(".")[0]
os.makedirs(basename, exist_ok=True)
aayushi-droid marked this conversation as resolved.
Show resolved Hide resolved
logging.info('Saving audio files in folder: {}'.format(basename))
pdfReader = PyPDF2.PdfFileReader(fp)
Expand All @@ -67,51 +98,42 @@ def save_audio(self, pdf_file_path, password=None):
self.engine.save_to_file(text, os.path.join(basename, basename + "_" + (str(num) + ".mp3")))
self.engine.runAndWait()

def read_book(self, pdf_file_path, password=None):
if not os.path.exists(pdf_file_path):
raise FileNotFoundError("File not found!")

if not pdf_file_path.endswith(".pdf"):
raise ValueError("File must be a pdf!")

with open(pdf_file_path, "rb") as fp:
pdfReader = PyPDF2.PdfFileReader(fp)
if pdfReader.isEncrypted:
logging.info("File is encrypted, trying to decrypt...")
pdfReader.decrypt(password)
pages = pdfReader.numPages
speak_text(self.engine, f"The book has total {str(pages)} pages!")
speak_text(self.engine, "Please enter the page number: ")
start_page = int(input("Please enter the page number: ")) - 1
reading = True
while reading:
if start_page > pages or start_page < 0:
speak_text(self.engine, "Invalid page number!")
speak_text(self.engine, f"The book has total {str(pages)} pages!")
start_page = int(input("Please enter the page number: "))
def read_book(self, input_file_path, password=None):
self.file_check(input_file_path)
print("Creating your audiobook... Please wait...")
book_dict, pages = self.create_json_book(input_file_path, password)
speak_text(self.engine, f"The book has total {str(pages)} pages!")
speak_text(self.engine, "Please enter the page number: ", display=False)
start_page = int(input("Please enter the page number: ")) - 1

reading = True
while reading:
if start_page > pages or start_page < 0:
speak_text(self.engine, "Invalid page number!")
speak_text(self.engine, f"The book has total {str(pages)} pages!")
start_page = int(input("Please enter the page number: "))

speak_text(self.engine, f"Reading page {str(start_page+1)}")
pageObj = pdfReader.getPage(start_page)
pageText = pageObj.extractText()
speak_text(self.engine, pageText)
speak_text(self.engine, f"Reading page {str(start_page+1)}")
pageText = book_dict[start_page]
speak_text(self.engine, pageText, display=False)

user_input = input("Please Select an option: \n 1. Type 'r' to read again: \n 2. Type 'p' to read previous page\n 3. Type 'n' to read next page\n 4. Type 'q' to quit:\n 5. Type page number to read that page:\n")
if user_input == "r":
speak_text(self.engine, f"Reading page {str(start_page+1)}")
continue
elif user_input == "p":
speak_text(self.engine, "Reading previous page")
start_page -= 1
continue
elif user_input == "n":
speak_text(self.engine, "Reading next page")
start_page += 1
continue
elif user_input == "q":
speak_text(self.engine, "Quitting the book!")
break
elif user_input.isnumeric():
start_page = int(user_input) - 1
else:
user_input = input("Please Select an option: \n 1. Type 'r' to read again: \n 2. Type 'p' to read previous page\n 3. Type 'n' to read next page\n 4. Type 'q' to quit:\n 5. Type page number to read that page:\n")
if user_input == "r":
speak_text(self.engine, f"Reading page {str(start_page+1)}")
continue
elif user_input == "p":
speak_text(self.engine, "Reading previous page")
start_page -= 1
continue
elif user_input == "n":
speak_text(self.engine, "Reading next page")
start_page += 1
continue
elif user_input == "q":
speak_text(self.engine, "Quitting the book!")
break
elif user_input.isnumeric():
start_page = int(user_input) - 1
else:
user_input = input("Please Select an option: \n 1. Type 'r' to read again: \n 2. Type 'p' to read previous page\n 3. Type 'n' to read next page\n 4. Type 'q' to quit:\n 5. Type page number to read that page:\n")
continue
continue
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="audiobook",
version="1.0.4",
version="2.0.0",
author="CodePerfectPlus",
author_email="deepak008@live.com",
description="Listen to your favourite audiobook",
Expand Down