Video Screen Capture using python and OpenCv and video not opening - python

importing the required packages
`import pyautogui
import cv2
import numpy as np`
Specify resolution
`resolution = (1920, 1080)`
Specify video codec
`codec = cv2.VideoWriter_fourcc(*"XVID")`
Specify frames rate. We can choose any
value and experiment with it
`fps = 60.0`
Creating a VideoWriter object
`out = cv2.VideoWriter("Recording.avi", codec, fps, resolution)`
Create an Empty window
`cv2.namedWindow("Live", cv2.WINDOW_NORMAL)`
# Resize this window
`cv2.resizeWindow("Live", 480, 270)`
`while True:
# Take screenshot using PyAutoGUI
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
# Optional: Display the recording screen
cv2.imshow('Live', frame)
# Stop recording when we press 'Esc'
k = cv2.waitKey(10) & 0xFF # press 'Esc' to exit
if k == 27:
break
# Release the Video writer
out.release()
# Destroy all windows
cv2.destroyAllWindows()`
the video was successfully but in the end I could not open the video file "Recording.avi" or to be specific my video player won't play it
any help?

Related

How to append an image to a video using OpenCV or FFMPEG or Moviepy or other libraries?

Do you know a library in Python to add a frame image to an existing video? The result video must have the same quality as the image.
I tried to use OpenCV to add google image: https://www.google.com/search?q=google&sxsrf=ALiCzsZhrdoHnOTmg0We4dxtguCqzma5Jg:1657603343101&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiTh8bTzfL4AhWhplYBHfXNAKwQ_AUoAXoECAIQAw&biw=1492&bih=739&dpr=1.25#imgrc=PRtenhDnrVrfOM
But the quality decreases when the video elongates.
Here is the final result video : https://drive.google.com/file/d/1ArDvoX-kN9H_oLbACk3kU1Cid93SMczC/view?usp=sharing
Here is my code using OpenCV:
image = cv2.imread(path_image)
height, width, dimensions = image.shape
video = cv2.VideoCapture(path_video)
frames = []
while(True):
ret, frame = video.read()
if ret == True:
frames.append(frame)
# frame = frame.resize(frame, (width, height), fx=0, fy=0, interpolation = cv2.INTER_CUBIC)
# Press S on keyboard
# to stop the process
if cv2.waitKey(1) & 0xFF == ord('s'):
break
# Break the loop
else:
break
video2 = cv2.VideoWriter(path_video,cv2.VideoWriter_fourcc('M','J','P','G'), 30, (width, height))
for frame in frames:
video2.write(frame)
video2.write(image)
video2.release() # releasing the video generated
print("Added {}".format(image_name))
I hope to improve the quality of this video.
I guess a simple way to achieve that using moviepy would be the following:
from moviepy.editor import *
from PIL import Image
import numpy as np
maxsize = (target_width, target_height)
jpg_image = Image.open(path_to_the_image)
# modify the image's resolution to be the target one
jpg_image.thumbnail(maxsize, Image.ANTIALIAS)
jpg_image = np.array(jpg_image)
image = ImageClip(jpg_image).set_duration(target_duration)
clip = VideoFileClip(path_to_the_video)
video = concatenate([image, clip], method="compose")
video.write_videofile("output_example.mp4", fps=target_fps)
As long as you set the target resolution of the image to match the video's one you are set with just that.

Webcam input sent to pyvirtualcam is blue(using pyvirtualcam and opencv)

I am trying to get input from my webcam using OpenCv and send it to a virtual camera using pyvirtualcam. For some reason when my webcam is displayed it gives it a blue filter. When i display my webcam without sending it to virtual camera there is no filter and everything works well.
import pyvirtualcam
import cv2
cap = cv2.VideoCapture(0)
with pyvirtualcam.Camera(width=1280, height=720, fps=20) as cam:
while True:
ret_val, frame = cap.read()
frame = cv2.resize(frame, (1280, 720), interpolation=cv2.BORDER_DEFAULT)
# cv2.imshow('my webcam', frame)
cam.send(frame)
cam.sleep_until_next_frame()
if cv2.waitKey(1) == 27:
break # esc to quit
cv2.destroyAllWindows()
OpenCV uses BGR as pixel format. pyvirtualcam expects RGB by default, but it supports BGR as well:
fmt = pyvirtualcam.PixelFormat.BGR
with pyvirtualcam.Camera(width=1280, height=720, fps=20, fmt=fmt) as cam:

how to fix opencv video freeze few second when sound play?

i try create application motion detector, when detected will play alarm. the program is running but the problem is when sound play video will freeze few second. so how to fix that?
I was tired of looking for references, but couldn't find anything.
import cv2
import numpy as np
import os
from playsound import playsound
# Video Capture
capture = cv2.VideoCapture(1)
fgbg = cv2.createBackgroundSubtractorMOG2(50, 200, True)
# frame
frameCount = 0
while(1):
# frame value
ret, frame = capture.read()
# cek frame
if not ret:
break
frameCount += 1
# resize frame
resizedFrame = cv2.resize(frame, (0, 0), fx=0.50, fy=0.50)
# foreground
fgmask = fgbg.apply(resizedFrame)
# jumlah Pixel
count = np.count_nonzero(fgmask)
if (frameCount > 1 and count > 5000):
playsound('tune.mp3')
os.system('cls' if os.name == 'nt' else 'clear')
print('Frame: %d, Pixel Count: %d' % (frameCount, count))
cv2.imshow('Frame', resizedFrame)
cv2.imshow('Mask', fgmask)
k = cv2.waitKey(1)
if k == 27:
break
capture.release()
cv2.destroyAllWindows()
Unfortunately, opencv when You play a sound from playsound. Even if You try calling plahsound using threads it will still freeze.
However, You can use Pygame's Mixer, which doesn't interrupt opencv's window. You can play a sound by:
from pygame import mixer
mixer.init()
sound = mixer.Sound('mysound.ogg')
sound.play()
However, I think Pygame's mixer is incompatible with mp3 files. You might wanna use .wav instead, or convert your mp3 file to .ogg format.

How can I achieve a 30 FPS frame rate using this Python screen recorder code?

I want a screen recorder. I thought of making my own.
I checked the internet and found: https://www.thepythoncode.com/code/make-screen-recorder-python
The Code:
import cv2
import numpy as np
import pyautogui
# Display screen resolution, get it from your OS settings
SCREEN_SIZE = (1366, 768)
# Define the codec
fourcc = cv2.VideoWriter_fourcc(*"XVID")
# Create the video write object
out = cv2.VideoWriter("output.avi", fourcc, 30.0, (SCREEN_SIZE))
while True:
# make a screenshot
img = pyautogui.screenshot()
# img = pyautogui.screenshot(region=(0, 0, 300, 400))
# convert these pixels to a proper numpy array to work with OpenCV
frame = np.array(img)
# convert colors from BGR to RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# write the frame
out.write(frame)
# show the frame
cv2.imshow("screenshot", frame)
# if the user clicks q, it exits
if cv2.waitKey(1) == ord("q"):
break
# Make sure everything is closed when exited
cv2.destroyAllWindows()
out.release()
The Problem:
When I run this, this works good. But it has a random speed after output. The fps is 30 but when I record for 1 minute, the video is 5 seconds or 10 minutes (random).
How do I make this recorder give output in 30 fps with the correct speed?
basically if you want to continue with your same code, you will have to compromise on resolution or frame rate.
My suggestion is to try the cv2.VideoCapture() functionality.
I am attaching the link to the webpage where there is a detailed step-by-step process where the author has achieved an FPS rate of 30.75.
Here's the link:
https://www.pyimagesearch.com/2017/02/06/faster-video-file-fps-with-cv2-videocapture-and-opencv/
The second half of the content present in the link has The faster, threaded method to reading video frames with OpenCV.
# import the necessary packages
from imutils.video import FileVideoStream
from imutils.video import FPS
import numpy as np
import argparse
import imutils
import time
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", required=True,
help="path to input video file")
args = vars(ap.parse_args())
# start the file video stream thread and allow the buffer to
# start to fill
print("[INFO] starting video file thread...")
fvs = FileVideoStream(args["video"]).start()
time.sleep(1.0)
# start the FPS timer
fps = FPS().start()
# loop over frames from the video file stream
while fvs.more():
# grab the frame from the threaded video file stream, resize
# it, and convert it to grayscale (while still retaining 3
# channels)
frame = fvs.read()
frame = imutils.resize(frame, width=450)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame = np.dstack([frame, frame, frame])
# display the size of the queue on the frame
cv2.putText(frame, "Queue Size: {}".format(fvs.Q.qsize()),
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
# show the frame and update the FPS counter
cv2.imshow("Frame", frame)
cv2.waitKey(1)
fps.update()
# stop the timer and display FPS information
fps.stop()
print("[INFO] elasped time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))
# do a bit of cleanup
cv2.destroyAllWindows()
fvs.stop()

My Screen Recorder built using OpenCV and PyAutoGUI records only one frame

I am building a Screen Recorder in Python using numpy, OpenCV and PyAutoGUI. I have used tkinter for GUI Purposes. The problem with my screen recorder is that it records only one frame when I click on the Record Screen Button and then the screen gets jammed and I can't do anything. Here is my code so far:
from tkinter import *
import cv2
import numpy as np
import pyautogui
resolution = (1366,768)
Specify video codec:
codec = cv2.VideoWriter_fourcc(*"XVID")
Specify name of Output file:
filename = "Recordings.avi"
Specify frames rate (we can choose any value and experiment with it):
fps = 30.0
Creating a VideoWriter object:
out = cv2.VideoWriter(filename, codec, fps, resolution)
def startRecording():
window.iconify()
while True:
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
def stopRecording():
cv2.destroyAllWindows()
out.release()
window.destroy()
window = Tk()
window.title("Screen Recorder")
window.geometry("400x150")
window.config(bg='pink')
recordButton = Button(window,text="Record(F9)",font=("Bell MT",20),width=20,command=startRecording)
recordButton.pack(pady=(10,0))
stopButton = Button(window,text="Stop(F10)",font=("Bell MT",20),width=20,command=stopRecording)
stopButton.pack(pady=(10,0))
mainloop()
You cannot do a blocking call in a button callback.
As you wrote it startRecording will never end and will hence block tkinter mainloop. The recording probably works but your UI becomes unresponsive.
Your best shot would be to schedule the recording (look for the after method): record one frame every x millisecond.
Here is a simplified example based on your original code (you need to complete it)
continueRecording = True # must be declared before stopRecording
window = Tk() # must be declared before recordOneFrame
def stopRecording():
global continueRecording
continueRecording = False
def recordOneFrame():
global continueRecording
img = pyautogui.screenshot()
# Convert the screenshot to a numpy array
frame = np.array(img)
# Convert it from BGR(Blue, Green, Red) to
# RGB(Red, Green, Blue)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Write it to the output file
out.write(frame)
if continueRecording:
window.after(round(1/25. * 1000),recordOneFrame)
def startRecording():
recordOneFrame()

Categories