cv2 wait key (Hoping to make it variable depending on latency) - python-3.x

When using my code bellow (It turns YouTube videos into ASCII with audio) The latency between the audio and video grows bigger each frame (I have tried many different wait times) I was wondering if there is a way to change the code to make it so the wait key changes depending on how much latency there is. I have only been coding for 6 months so sorry if there is any bad code.
import pytube
import os
import cv2
import PIL.Image
import winsound
from moviepy.editor import *
from pydub import AudioSegment
import threading
import time
##################################################
# downloads the youtube video and lets you input the path for where it should be saved
url = input ("Enter the you youtube url: \n\n")
path = input ("Enter the path where you want the youtube video to be saved: \n\n")
try:
youtube = pytube.YouTube(url)
streams = youtube.streams.all()
video = youtube.streams.get_highest_resolution()
video.download(path)
print ("Done!")
except:
print ("\nYoutube video has coppy righted material so it can not be downloaded. Try again with a different video")
##################################################
#locates all the files with the file extension .mp4
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith(".mp4"):
file_name = (file)
file_path = (os.path.join(root,file))
print (file_name)
print (file_path)
##################################################
mp3_file = (path+"\\")
mp3_file = (mp3_file+"audio.mp3")
mp4_file = (path+"\\")
mp4_file = (mp4_file+file_name)
VideoClip = VideoFileClip(mp4_file)
audioclip = VideoClip.audio
audioclip.write_audiofile(mp3_file)
audioclip.close()
VideoClip.close()
sound = AudioSegment.from_mp3(mp3_file)
sound.export(path+"/audio.wav", format = "wav")
##################################################
def a():
# Ascii characters used to create the output
ASCII_CHARS = ["#", "#", "S", "%", "?", "*", "+", ";", ":", ",", "."]
def resized_gray_image(image ,new_width=80):
width,height = image.size
aspect_ratio = height/width
new_height = int(aspect_ratio * new_width)
resized_gray_image = image.resize((new_width,new_height)).convert('L')
return resized_gray_image
def pix2chars(image):
pixels = image.getdata()
characters = "".join([ASCII_CHARS[pixel//25] for pixel in pixels])
return characters
def generate_frame(image,new_width=80):
new_image_data = pix2chars(resized_gray_image(image))
total_pixels = len(new_image_data)
ascii_image = "\n".join([new_image_data[index:(index+new_width)] for index in range(0, total_pixels, new_width)])
sys.stdout.write(ascii_image)
os.system('cls' if os.name == 'nt' else 'clear')
cap = cv2.VideoCapture(mp4_file)
print (cap)
try:
while True:
ret,frame = cap.read()
cv2.imshow("frame",frame)
generate_frame(PIL.Image.fromarray(frame))
cv2.waitKey(1)
except:
threading.Thread(target=c).start()
##################################################
def b():
winsound.PlaySound(path+"/audio.wav",winsound.SND_FILENAME)
##################################################
def c ():
os.remove (mp3_file)
os.remove (mp4_file)
os.remove (path+"/audio.wav")
threading.Thread(target=a).start()
threading.Thread(target=b).start()

Related

Checking if a Reddit post is a video or not

I'm making a bot that downloads posts from a subreddit I selected, but I only want to download photos. My code already makes sure that the post is not a text but I'm not able to check if the video or not. If the post is a video, the program should just skip it.
Here is my code so far:
from InstagramAPI import InstagramAPI
import praw
import requests
import urllib.request
import time
import keyboard
from PIL import Image
import math
#make a reddit acount and look up how to find this stuff. its called PRAW
reddit = praw.Reddit(client_id='***',
client_secret='***',
username='',
password='',
user_agent='chrome')
def DLimage(url, filePath, fileName):
fullPath = filePath + fileName + '.jpg'
urllib.request.urlretrieve(url, fullPath)
#folder path to store downloaded images
filePath = "/Users/***/AppBot/WTF/"
subreddit = reddit.subreddit('videos') #subreddit to take images from
waitTime = 2 #to prevent reddit badgateway error. DONt change
numRounds = 100 #how many posts
postFrequency = 600 # how often to post in seconds.
numPics = 100 #how many pics per post
for x in range(numRounds):
new_memes = subreddit.top('all') #.hot/.rising/.new reddit sorting algorithm
authors = []
photoAlbum = []
print("Round/post number:", x)
for subbmission in new_memes:
if subbmission.preview == True: #checking if post is only text.
#print("Post was text, skipping to next post.")
pass
else:
continue
url = subbmission.url
time.sleep(waitTime)
fileName = str(subbmission)
fullPath = filePath + fileName + '.jpg'
#print(fullPath)
time.sleep(waitTime)
#print(url)
try:
DLimage(url, filePath, fileName)
except:
print("scratch that, next post.")
continue
time.sleep(waitTime)
img = Image.open(fullPath)
width, height = img.size
#img = img.resize((1000, 1020), Image.NEAREST) #image resize. width/height
img = img.convert("RGB")
img.save(fullPath)
time.sleep(postFrequency)

Python face_recognition and saving file with cv2

This is my first time posting a question so pardon any mistakes. I'm trying to write a script that will do face_recognition and save the video file at the same time and running into I think latency issues. When there isn't a face to detect it saves the video file fine. When there is a face though it seems to get every other frame. I feel like that is because it's doing computations for finding the face which prevents it from saving the next frame. Is there a way around this? maybe threading or multiprocessing?
import face_recognition as fr
import os
import face_recognition
import numpy as np
import cv2
def get_encoded_faces():
encoded = {}
for dirpath, dnames, fnames in os.walk("./faces"):
for f in fnames:
if f.endswith(".jpg") or f.endswith(".png"):
face = fr.load_image_file("faces/" + f)
encoding = fr.face_encodings(face)[0]
encoded[f.split(".")[0]] = encoding
return encoded
def unknown_image_encoded(img):
face = fr.load_image_file("faces/" + img)
encoding = fr.face_encodings(face)[0]
return encoding
faces = get_encoded_faces()
faces_encoded = list(faces.values())
known_face_names = list(faces.keys())
def FindFace(img):
face_locations = face_recognition.face_locations(img)
unknown_face_encodings = face_recognition.face_encodings(img, face_locations)
face_names = []
for face_encoding in unknown_face_encodings:
matches = face_recognition.compare_faces(faces_encoded, face_encoding)
name = "Unknown"
face_distances = face_recognition.face_distance(faces_encoded, face_encoding)
best_match_index = np.argmin(face_distances)
if matches[best_match_index]:
name = known_face_names[best_match_index]
face_names.append(name)
#cv2.imwrite('final_image.png',img)
video_capture = cv2.VideoCapture(1)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 20.0, (640,480))
if not video_capture.isOpened():
raise Exception("Could not open video device")
while(video_capture.isOpened()):
ret, frame = video_capture.read()
out.write(frame)
#cv2.imshow('Video', frame)
FindFace(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()

Python watchdog module duplicate events (edit: was not an watchdog issue)

I am creating a python script that will identify changes to a log file and print some data from the new logs.
I use watchdog to create an event handler and everything seems to work fine except from that, I get duplicate events every time I modify the file. I checked creation and delete, they both work as expected and trigger one time.
I have read the similar question which explains having a created and a modified event when I save a file but this is not my case. I just get two modification events.
Here is my code:
import os, sys, time
import subprocess
import threading
import win32print
from tkinter import filedialog
from tkinter import *
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class Handler(FileSystemEventHandler):
# docstring for FileSystemEventHandler
def __init__(self, observer, filename, dirname):
# super(Handler, FileSystemEventHandler).__init__(self,)
self.observer = observer
self.filename = filename
self.dirname = dirname
print("Handler filename = " , self.filename)
print("Handler dirname = " , self.dirname)
def on_modified(self, event):
if self.filename == event.src_path:
print("The file was modified")
print (event.src_path)
# go get the last line and print the data
# try:
# hJob = win32print.StartDocPrinter (hPrinter, 1, ("test of raw data", None, "RAW"))
# try:
# win32print.StartPagePrinter (hPrinter)
# win32print.WritePrinter (hPrinter, raw_data)
# win32print.EndPagePrinter (hPrinter)
# finally:
# win32print.EndDocPrinter (hPrinter)
# finally:
# win32print.ClosePrinter (hPrinter)
def on_created(self, event):
print("A file was created (", event.src_path, ")")
def on_deleted(self, event):
print("A file was deleted (", event.src_path, ")")
if __name__ == "__main__":
Flags=2
Name=None
Level=1
printers = win32print.EnumPrinters(Flags, Name, Level)
print("\nChoose a printer to use:")
i=1
for p in printers:
print(i,')' , p[2])
i = i+1
if sys.version_info >= (3,):
raw_data = bytes ("This is a test", "utf-8")
else:
raw_data = "This is a test"
printer = int(input())
printer_name = printers[printer-1][2] #win32print.GetDefaultPrinter ()
print("You chose ", printer_name, "\nI will now print from the specified file with this printer")
hPrinter = win32print.OpenPrinter (printer_name)
# root = Tk()
# root.filename = filedialog.askopenfilename(initialdir = "/Desktop",title = "Select file",filetypes = (("log files","*.log"),("all files","*.*")))
file_path = "some_file_path" # root.filename
file_directory = os.path.dirname(file_path)
# print (file_path)
print (file_directory)
observer = Observer()
event_handler = Handler(observer, file_path, file_directory)
observer.schedule(event_handler, path=file_directory, recursive=False)
observer.start()
observer.join()
any ideas would be appreciated
EDIT:
After some debugging I found out that Windows10 is changing the file modification time twice every time I save it.
The proof of concept code is this:
prev_modification_time = os.path.getmtime(file_path)
while True:
current_mod_time = os.path.getmtime(file_path)
if prev_modification_time != current_mod_time :
print ("the file was modified, last modification time is: ", current_mod_time)
prev_modification_time = current_mod_time
pass
Final edit:
After testing my code on linux (Debian Stretch to be exact) it worked like a charm. So this combined with the previous edit probably shows that watchdog works fine and it is windows10 that has some issue. Should I post it on a different question or here?

Error using win32com & pttsx3 for Python Voice Recognition

'''
Please help me out at this stage.i want to do this program with win32com & pyttsx 3. tried both but not working . Below is my code please check and help.
I want program to answer me back as as per defined answers.
Program is working fine and replying as a text but i am not getting any response by voice..
'''
# audio.py File
import pyaudio
import speech_recognition as sr
import pyglet
from commands import Commander
import subprocess
import win32com.client as wincl
import wave
import pyttsx3
running = True #ss
def say(text):
speak = wincl("SAPI.SpVoice")
speak.Speak('say ' + text, shell=True)
def play_audio(filename):
chunk = 1024
wf = wave.open(filename, 'rb')
pa = pyaudio.PyAudio()
stream = pa.open(
format=pa.get_format_from_width(wf.getsampwidth()),
channels = wf.getnchannels(),
rate = wf.getframerate(),
output = True
)
data_stream = wf.readframes(chunk)
while data_stream:
stream.write(data_stream)
data_stream = wf.readframes(chunk)
stream.close()
pa.terminate()
play_audio("./audio/after.wav")
# Upper part is to play sound using pyaudio
r = sr.Recognizer()
cmd = Commander() #
def initSpeech():
print("Listening.....")
play_audio("./audio/before.wav")
with sr.Microphone() as source:
print("Say Something")
audio = r.listen(source)
play_audio("./audio/before.wav")
command = ""
try:
command = r.recognize_google(audio)
except:
print("Couldn't understand you bro. ")
print("Your Command: ")
print(command)
if command == "quit":
running = False #
#echo('You Said: ' + command)
cmd.discover(command) #
#speak.Speak('You Said: ' + command) -------> no comment
while running == True:
initSpeech()
-----------------------------------------------------------------------------------------------------
# commands.py File
import subprocess
import os
class Commander:
def __init__(self):
self.confirm = ["yes", "affirmative", "si", "sure", "do it", "yeah", "confirm"]
self.cancel = ["no", "negative", "negative soldier", "don't", "wait", "cancel"]
def discover(self, text):
if "what" in text and "your name" in text:
if "my" in text:
self.respond("You haven't told your name yet")
self.respond("My name is python commander. How are you")
def respond(self, response):
print(response)
speak.Speak('say ' + response, shell=True) # This Speak is
from pywin32

How to pause/interupt with keyboard

I'm using the following script to play all the WAV files in the current path. I will be modifying it to print the output of some text files. That part is easy.
Need to know how/where in the loop of playing the WAV files, where to add some code to pause/interupt the execution of the code with the keyboard.
#!/usr/bin/python3
import vlc
import time
import glob
wav_files = glob.glob("*.wav")
instance=vlc.Instance(["--no-sub-autodetect-file"])
# You should not recreate a player for each file, just reuse the same
# player
player=instance.media_player_new()
for wav in wav_files:
player.set_mrl(wav)
player.play()
playing = set([1,2,3,4])
time.sleep(5) #Give time to get going
duration = player.get_length() / 1000
mm, ss = divmod(duration, 60)
print("Playing", wav, "Length:", "%02d:%02d" % (mm,ss))
while True:
state = player.get_state()
if state not in playing:
break
continue
Steal the getch right out of vlc.py
I've added the windows option, as you didn't specify an OS.
#!/usr/bin/python3
import vlc
import time
import glob
import sys
import termios, tty
try:
from msvcrt import getch # try to import Windows version
except ImportError:
def getch(): # getchar(), getc(stdin) #PYCHOK flake
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
return ch
wav_files = glob.glob("*.wav")
print("Play List")
for f in wav_files:
print(f)
instance=vlc.Instance(["--no-sub-autodetect-file"])
# You should not recreate a player for each file, just reuse the same
# player
player=instance.media_player_new()
for wav in wav_files:
player.set_mrl(wav)
player.play()
playing = set([1,2,3,4])
time.sleep(1) #Give time to get going
duration = player.get_length() / 1000
mm, ss = divmod(duration, 60)
print("Playing", wav, "Length:", "%02d:%02d" % (mm,ss))
while True:
state = player.get_state()
if state not in playing:
break
k = getch()
if k in ["N","n"]:#Next
player.stop()
break
elif k in ["Q","q"]:#Quit
player.stop()
sys.exit()
break
elif k == " ":#Toggle Pause
player.pause()
else:
print("[Q - Quit, N - Next, Space - Pause]")
continue

Resources