convert your book to an audiobook
Problem
You need the audiobook version of your favourite book. However, you are on a strict budget and you don’t want to buy the audiobook. You want to make your own audiobook, for free, of course.
Solution
I found this project idea on YouTube, see here. The first 2 minutes were more than enough for me :), but I found the project idea interesting. The source code of the guy is here.
I tried it under Linux and it sounded like a robot. Can we do it better? Of course! I won’t give a complete solution but you can put together your own solution using my previous 2 posts:
text to speech
Problem #1
You have a text and you want to convert it to audio (possibly to .mp3).
Solution #1
The gTTS module can do this for you.
“gTTS
(Google Text-to-Speech), a Python library and CLI tool to interface with Google Translate’s text-to-speech API. Writes spoken mp3
data to a file, a file-like object (bytestring) for further audio manipulation, or stdout
. It features flexible pre-processing and tokenizing, as well as automatic retrieval of supported languages.” (source)
Example:
from gtts import gTTS
TEXT = """
Python is an interpreted, high-level and general-purpose programming
language. Created by Guido van Rossum and first released in 1991, Python's
design philosophy emphasizes code readability with its notable use of
significant whitespace. Its language constructs and object-oriented
approach aim to help programmers write clear, logical code for small
and large-scale projects.
""".replace("\n", " ")
def main():
tts = gTTS(text=TEXT, lang='en')
tts.save("audio.mp3")
print("done")
The text is read by a pleasant female voice in good quality.
The reader takes a little pause at every end of line, that’s why newline characters are replaced by a space. This way the reading is fluid.
Problem #2
There is one little problem. I find the reading speed in audio.mp3 a bit slow. When you watch a YouTube video, there you have the possibility to speed up the audio by 25%, 50%, etc. How to play back audio.mp3 a bit faster?
Solution #2
$ play audio.mp3 tempo 1.15
or
$ mplayer audio.mp3 -speed 1.15 -af scaletempo
It means 15% faster playback.
gTTS from the command-line
If you install the package gtts, you also get a command-line program called gtts-cli. Some examples:
$ gtts-cli --all
^^^ List all languages. At the time of writing, the list contains 78 entries. (Hungarian is also there).
$ gtts-cli 'hello' | play -t mp3 -
^^^ Play the sound directly.
$ gtts-cli "bonjour tout le monde" --lang fr | play -t mp3 -
^^^ Specify the language of the text.
$ gtts-cli "c'est la vie" --lang fr --output cestlavie.mp3
^^^ Save the sound in an .mp3 file.
Links
- Speech Recognition in Python (Text to speech) , I heard about gTTS in this post
- Python Text To Speech | pyttsx module
Notes
I also tried the pyttsx library under Linux but the quality was terrible. It calls the command espeak and it reads the text like a f* robot. No, thanks. Maybe it sounds better under Windows (under Windows there is a different text to speech engine); I didn’t try that.
extract text from a PDF file
Problem
You have a PDF file and you want to extract text from it.
Solution
You can use the PyPDF2 module for this purpose.
import PyPDF2
def main():
book = open('book.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(book)
pages = pdfReader.numPages
page = pdfReader.getPage(0) # 1st page
text = page.extractText()
print(text)
Note that indexing starts at 0. So if you open your PDF with Adobe Reader for instance and you locate page 20, in the source code you must use getPage(19)
.
Links
- PyPDF2 on GitHub
Exercise
Write a program that extracts all pages of a PDF and saves the content of the pages to separate files, e.g. page0.txt
, page1.txt
, etc.
Python Developer’s Guide
If you want to contribute to the Python language, start here: https://devguide.python.org .
Python 3.9 is coming
See this post to have an idea of the new features of Python 3.9: https://ayushi7rawat.hashnode.dev/python-39-all-you-need-to-know .
More details here: https://docs.python.org/3.9/whatsnew/3.9.html .
extract all images from a 4chan thread
If you are a 4chan user, then this little project of mine can be useful for you: https://github.com/jabbalaci/4chan-Thread-Images . It can extract all the images from a 4chan thread. It uses the official API of 4chan, it doesn’t do any webscraping.
angle between two lines
Problem
You have two lines. What is the angle between them?
Or, you have 3 points, say A, B and C. If you go from A to B (vector 1), then from B to C (vector 2), then what is the angle at point B between the two vectors?
Solution
There is a nice blog post about it here: Find the Angle between three points from 2D using python.
Here is a Python code that is based on the one that you can find in the aforementioned blog post:
import math from typing import NamedTuple class Point(NamedTuple): x: int y: int def angle(a: Point, b: Point, c: Point) -> float: ang = math.degrees(math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0])) return ang + 360 if ang < 0 else ang
monitoring key presses in a console application in a thread
Problem
I wrote a console application that shows a table and updates the screen every second. Later, I wanted to add a table sorting functionality. For instance, if you press ‘b’, then the table is sorted by the 2nd column, pressing ‘c’ would sort the table by the 3rd column, etc.
I found some keyboard monitoring libraries but they were all blocking, i.e. you had to call a function which was waiting for a key press. If you didn’t press any key, this function was just waiting.
However, in my program I had an infinite loop that was doing the following steps: (1) clear the screen, (2) draw the table, (3) repeat. If I add anywhere the keyboard monitoring, the loop gets blocked somewhere.
Solution
I asked this question on reddit (see here), and /u/Viddog4 suggested that I should use a thread. Of course! I have the main loop that draws the table, and I have a thread in the background that monitors the keyboard.
Here is a simplified code that demonstrates the idea:
#!/usr/bin/env python3 """ pip3 install pynput xlib """ import threading from time import sleep from pynput.keyboard import Key, Listener class myThread(threading.Thread): def __init__(self, _id, name): super().__init__() self.daemon = True # daemon threads are killed as soon as the main program exits self._id = _id self.name = name def on_press(self, key): print('{0} pressed'.format(key)) def on_release(self, key): print('{0} release'.format(key)) if key == Key.esc: # Stop listener return False def run(self): with Listener(on_press=self.on_press, on_release=self.on_release) as listener: listener.join() def main(): thread1 = myThread(1, "thread_1") thread1.start() # main loop: while True: print(".", flush=True) try: sleep(1) except KeyboardInterrupt: break ########## if __name__ == "__main__": main()
You can stop the thread with Esc. You can terminate the whole program with Ctrl+C. The thread is registered as a daemon thread, which means that if the main program exits (e.g. you press Ctrl+C), then daemon threads are automatically stopped.
Links
- pynput, keyboard monitoring library
- An Intro to Threading in Python, to learn more about threads
- Different ways to kill a Thread, I chose to set it as a daemon thread
simple keylogger
I was working on a console application and I wanted to add the functionality to listen to keyboard presses in an infinite loop. I used the pynput library and tried this basic code that I found on the project’s web site:
# pip3 install pynput xlib
# xlib is required for mouse support
from pynput.keyboard import Key, Listener
def on_press(key):
print("{0} pressed".format(key))
def on_release(key):
print("{0} release".format(key))
if key == Key.esc:
# Stop listener
return False
# Collect events until released
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
It worked well. I let it run and switched to another window when I noticed that the script was still monitoring what keys I press, though I was in another window! So it monitors the keyboard globally. And, under Linux, I didn’t even have to start it with sudo.
So, if you need a simple keylogger, here it is :) You don’t need to add much to the code above to have a working keylogger.
Update (20240204):
Here is a slightly longer example:
from pynput.keyboard import Key, Listener
def on_press(key):
print("{0} pressed".format(key))
if key == Key.esc:
print("# you pressed ESC")
try:
if key.char == "a":
print("# you pressed 'a'")
#
except:
pass
def on_release(key):
print("{0} release".format(key))
print("---")
def main():
print("keylogger running...")
with Listener(on_press=on_press, on_release=on_release) as listener:
try:
listener.join()
except KeyboardInterrupt:
print()
if __name__ == "__main__":
main()
flush the stdin
Problem
I wrote a terminal application that was reading key presses from the keyboard using the pynput library. When the program terminated, it printed on the screen the keys that I pressed while the program was running. How to get rid of this side effect?
Solution
First I tried sys.stdin.flush()
but it didn’t help. However, the following worked:
import sys import termios termios.tcflush(sys.stdin, termios.TCIOFLUSH)
Calling this line before quitting successfully flushed the standard input.
You must be logged in to post a comment.