Skip to content

Commit

Permalink
Support: txt file support added
Browse files Browse the repository at this point in the history
  • Loading branch information
codeperfectplus committed Oct 15, 2022
1 parent f010fe0 commit ecab654
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 70 deletions.
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)
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

0 comments on commit ecab654

Please sign in to comment.