I'm very new to codecs. I have 100 frames and I want to convert them into a video using H265 encoder. previously I tried with h264 and video generated with file size 2.5MB. Now when I tried with hvc1 and the output video file is much bigger(65MB). I also tried with hev1 still getting the same 65MB file. But heard that h265 will generate a lesser file compared to h264. Can anyone help me with this problem?
import cv2
import os
import re
image_folder = 'backend/data'
video_name = 'backend/h265/output.mp4'
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
def natural_sort_key(s, _nsre=re.compile('([0-9]+)')):
return [
int(text)
if text.isdigit() else text.lower()
for text in _nsre.split(s)]
sorted_images = sorted(images, key=natural_sort_key)
frame = cv2.imread(os.path.join(image_folder, sorted_images[0]))
height, width, layers = frame.shape
fourcc = cv2.VideoWriter_fourcc(*'hev1') #hvc1 and hev1 are two codec ids of hevc
video = cv2.VideoWriter(video_name, fourcc, 27, (width,height))
for image in sorted_images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
am I using the correct codec ids of hevc for in this code?
Related
I have a sequence of grayscale images. using python code of opencv, I made a video out of these grayscale images.
import cv2
import numpy as np
A = readimages(img_path) # A is a list of uint8 images of size similar to framesize
framesize = (480,640)
out = cv2.VideoWriter('output_video.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 30.0, framesize, isColor = False)
for img in A:
out.write(cv2.flip(img,0))
out.release()
the resultant video as shown in the image below (left part) just shows a fraction of the input images along with multiple lines. any help please.
In this case, the images dtype must uint8, before writing into video file. The new code works fine.
import cv2
import numpy as np
A = readimages(img_path) # A is a list of uint8 images of size similar to framesize
framesize = (480,640)
out = cv2.VideoWriter('output_video.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 30.0, framesize, isColor = False)
for img in A:
out.write(img.astype('uint8'))
out.release()
I want to pipe images to a virtual video device (e.g. /dev/video0), the images are created inside a loop with the desired frame rate.
In this minimal example i only two arrays which alternate in the cv2 window. Now i look for a good solution to pipe the arrays to the virtual device.
I saw that ffmpeg-python can run asynchronous with ffmpeg.run_async(), but so far i could not make anything work with this package.
example code without the ffmpeg stuff:
#!/usr/bin/env python3
import cv2
import numpy as np
import time
window_name = 'virtual-camera'
cv2.namedWindow(window_name, cv2.WINDOW_GUI_EXPANDED)
img1 = np.random.uniform(0, 255, (1080, 1440, 3)).astype('uint8')
img2 = np.random.uniform(0, 255, (1080, 1440, 3)).astype('uint8')
for i in range(125):
time.sleep(0.04)
if i % 2:
img = img1
else:
img = img2
cv2.imshow(window_name, img)
cv2.waitKey(1)
cv2.destroyAllWindows()
First of all, you would have to setup a virtual camera, with for example v4l2loopback. See here for how to install it (ignore the usage examples).
Then, you can just write to the virtual camera like to a normal file (that is, let openCV write the images to say /dev/video0; how to do that you have to find out yourself because im not an expert with openCV).
In the end, you can use ffmpeg-python with /dev/video0 as input file, do something with the video, and that's it !
As Programmer wrote in his answer, it is possible to create a dummy device with the package v4l2loopback. To publish images, videos or the desktop to the dummy device was already easy with ffmpeg, but i want to pipe it directly from the python script - where i capture the images - to the dummy device. I still think it's possible with ffmpeg-python, but i found this great answer from Alp which sheds light on the darkness. The package pyfakewebcam is a perfect solution for the problem.
For the sake of completeness, here is my extended minimal working example:
#!/usr/bin/env python3
import time
import cv2
import numpy as np
import pyfakewebcam
WIDTH = 1440
HEIGHT = 1080
DEVICE = '/dev/video0'
fake_cam = pyfakewebcam.FakeWebcam(DEVICE, WIDTH, HEIGHT)
window_name = 'virtual-camera'
cv2.namedWindow(window_name, cv2.WINDOW_GUI_EXPANDED)
img1 = np.random.uniform(0, 255, (HEIGHT, WIDTH, 3)).astype('uint8')
img2 = np.random.uniform(0, 255, (HEIGHT, WIDTH, 3)).astype('uint8')
for i in range(125):
time.sleep(0.04)
if i % 2:
img = img1
else:
img = img2
fake_cam.schedule_frame(img)
cv2.imshow(window_name, img)
cv2.waitKey(1)
cv2.destroyAllWindows()
I am currently processing some audio data. I have an audio file that I have created from splitting a larger file on silence using pydub.
However, if I take this audio file after exporting it with pydub, and then convert the AudioSegment's array to numpy array, and re-write it using soundfile, I get an audio file written that is about half the speed as it was originally. What could be going wrong?
import soundfile as sf
import numpy as np
from pydub import AudioSegment, effects
from pathlib import Path
# This code takes a large .mp3 file ("original_audio_mp3") with sample rate of 44100 khz
sound = AudioSegment.from_file(original_audio_mp3)
if sound.frame_rate != desired_sample_rate:
sound = sound.set_frame_rate(desired_sample_rate) # convert to 16000 khz sample rate
sound = effects.normalize(sound) # normalize audio file
dBFS = sound.dBFS # get decibels relative to full scale
sound_chunks = split_on_silence(sound,
min_silence_len = 200, # measured in ms
silence_thresh = dBFS -30 # if DBFS goes 30 below the file's dBFS it will be considered "silence"
)
# this "audio_segment_0.wav" file came from the above code.
audio_file_path = Path("audio_segment_0.wav")
raw_audio = AudioSegment.from_file(audio_file_path).set_frame_rate(16000)
# append 200 ms of silence to beginning and end of file
raw_audio = effects.normalize(raw_audio)
silence = AudioSegment.silent(duration = 200, frame_rate = 16000)
raw_audio_w_silence = silence + raw_audio + silence
# export it
raw_audio_w_silence.export("pydub_audio.wav", format = 'wav') # the output from this sounds completely OK.
# read audio, manipulate and write with soundfile
new_audio = AudioSegment.from_file("pydub_audio.wav").set_frame_rate(16000)
new_audio_signal = np.array(new_audio.get_array_of_samples(), dtype = np.float32) / 32768.0 # scale to between [-1.0, 1.0]
# the output from down here using the scaled numpy array sounds about half the speed as the first.
sf.write("soundfile_export.wav", data = new_audio_signal, samplerate = new_audio.frame_rate, format = 'wav')
I am creating a python program to record my desktop screen.
But the output of this code is in very low quality and blurry.
Can anyone help me in capturing (screen capturing) in high quality.
Like the screen recorder like OBS studio and Camtasia do.
what can i do improve my quality change my extention ,codec ,etc. please mention.
import cv2
import numpy as np
import datetime
from PIL import Image, ImageTk, ImageGrab
date = datetime.datetime.now()
filename='rec_%s-%s-%s-%s%s%s.mp4' % (date.year, date.month, date.day,
date.hour, date.minute, date.second)
fourcc = cv2.VideoWriter_fourcc(*'X264')
frame_rate = 16
SCREEN_SIZE = (960,540)
out = cv2.VideoWriter(filename, fourcc,framerate, SCREEN_SIZE)
while True:
img = ImageGrab.grab()
frame = np.array(img)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
out.write(frame)
cv2.imshow('screenshot', frame)
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
out.release()
frame_rate = 16
SCREEN_SIZE = (960,540)
Both of this are too low, you probably want your frame_rate to be 30, and your screen size to be 1920x1080p.
Also just has an extra info:
.mp4 is a bad format for screen recording, I know OBS recommended using .flv because it doesn't corrupt the whole file if the recording end abruptly, unlike .mp4.
I have used cv2 to combine a folder of images into a video using cv2 but the speed in which the video plays is too slow is there a way to increase the speed?
import cv2
import os
image_folder = 'd:/deep/data'
video_name = 'video.avi'
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 1, (width,height))
for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
to set fps i tried this peice of code and it still dint work
import cv2
import os
import numpy as np
image_folder = 'd:/deep/data'
video_name = 'video.avi'
fps=100
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 1, (width,height),fps)
for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
cv2.VideoWriter([filename, fourcc, fps, frameSize[, isColor]]) → <VideoWriter object>
Check documentation and set fps. your current framerate is 1 fps .
Edit :
Should be something like this :
fourcc = cv2.VideoWriter_fourcc(*'DIVX') # codec for windows (supported by your device?)
fps = 25.0 # adjust the framerate here
cv2.ViewoWriter(video_name, fourcc, fps , (width,height))
this is the right code
import cv2
import os
import numpy as np
image_folder = 'd:/deep/data'
video_name = 'video.avi'
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
fourcc = cv2.VideoWriter_fourcc(*'XVID')
video = cv2.VideoWriter(video_name, fourcc,15.0, (width,height))
for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()