So I am creating this scrip that concatenates videos of images with audio attached to them, I previously created the videos with another python file by adding audio to the image and converting it into video.
The videos work individually but when I concatenate them, the final video glitches and looks weird
Code:
from moviepy.editor import *
clip1 = VideoFileClip("final_video0.mp4")
clip2 = VideoFileClip("final_video1.mp4")
clip3 = VideoFileClip("final_video2.mp4")
clip4 = VideoFileClip("final_video3.mp4")
clip5 = VideoFileClip("final_video4.mp4")
clip6 = VideoFileClip("final_video5.mp4")
clip7 = VideoFileClip("final_video6.mp4")
clip8 = VideoFileClip("final_video7.mp4")
clip9 = VideoFileClip("final_video8.mp4")
clip10 = VideoFileClip("final_video9.mp4")
final = concatenate_videoclips([clip1, clip2, clip3, clip4, clip5, clip6])
final.write_videofile("merged.mp4")
Related
I have been using pytube to create my youtube video downloader and after the video is done downloading and compiling and i play it, it plays for only a few seconds then just displays a still image while the audio continues in background
These are the functions in file "module.py"
import pytube
from moviepy.editor import *
import os.path
def video(link):
yt = pytube.YouTube(link)
streamlist = []
for stream in yt.streams.filter():
streamlist.append(stream)
finalstreamlist = []
for i in streamlist:
if i.resolution == "1080p" and i.mime_type == "video/mp4":
finalstreamlist.append(i)
stream = yt.streams.get_by_itag(finalstreamlist[0].itag)
stream.download(r"C:\Users\pc\PycharmProjects\youtube")
return [stream.title, yt.length]
def audio(link):
yt = pytube.YouTube(link)
streamlist = []
for stream in yt.streams.filter():
streamlist.append(stream)
finalstreamlist = []
for i in streamlist:
if i.mime_type == "audio/mp4":
finalstreamlist.append(i)
stream = yt.streams.get_by_itag(finalstreamlist[0].itag)
stream.download(r"C:\Users\pc\PycharmProjects\youtube", "Audio.mp4")
return ["Audio.mp4",yt.length]
def mixer(video,audio,title):
videoclip = VideoFileClip(video)
audioclip = AudioFileClip(audio)
videoclip2 = videoclip.set_audio(audioclip)
videoclip2.write_videofile(title)
And this is the "main.py" file:
from modules import *
import time
link = "https://www.youtube.com/watch?v=CLk7A7HXhYQ"
vtitle = video(link)[0] + ".mp4"
atitle = audio(link)[0]
print("Files Downloaded")
time.sleep(1)
print("Compiling")
mixer(vtitle,atitle,vtitle)
print("FileDone")
I tried your code and it downloads video file correctly but problem is when it mixs video and audio.
I think problem it that it writes new video with the same name as original video - probably it doesn't load old video to memory but it reads it all time from file - and this makes conflict.
I think you should write new video with new (temporary) filename and later rename it to expected name. Or you should download video with temporary name (i.e. video.mp4)
My code which I used for tests
import pytube
from moviepy.editor import *
import os
BASE = os.path.dirname(os.path.abspath(__file__))
def video(link):
yt = pytube.YouTube(link)
finalstreamlist = yt.streams.filter(resolution='1080p', mime_type='video/mp4')
itag = finalstreamlist[0].itag
print('video itag:', itag)
stream = yt.streams.get_by_itag(itag)
stream.download(os.path.join(BASE, 'youtube'), 'video.mp4')
return [os.path.join(BASE, 'youtube/video.mp4'), stream.title, yt.length]
def audio(link):
yt = pytube.YouTube(link)
finalstreamlist = yt.streams.filter(mime_type='video/mp4')
itag = finalstreamlist[0].itag
print('audio itag:', itag)
stream = yt.streams.get_by_itag(itag)
stream.download(os.path.join(BASE, 'youtube'), 'audio.mp4')
return [os.path.join(BASE, 'youtube/audio.mp4'), stream.title, yt.length]
def mixer(video, audio, title):
videoclip = VideoFileClip(video)
audioclip = AudioFileClip(audio)
new_videoclip = videoclip.set_audio(audioclip)
new_videoclip.write_videofile(title)
# --- main ---
link = 'https://www.youtube.com/watch?v=CLk7A7HXhYQ'
print('Downloading')
v = video(link)
a = audio(link)
print('Downloaded')
print('Compiling')
output = os.path.join(BASE, v[1] + '.mp4')
mixer(v[0], a[0], output)
print('Compilied')
I'm trying to write an AWS Lambda function that takes a TIFF, converts it to JPEG, then outputs it in base64 so that lambda can serve it. But I keep running into malformed response, or issues with reshape_as_image saying axes doesn't match array.
My understanding was that the return of memfile.read() would allow me to use reshape_as_image, however my logic seems faulty.
Without saving to disk, how can I get from memfile to a base64 jpeg representation so that lambda can serve it? I've also tried pillow but I think the necessary step is where I'm failing.
def get_image(self, driver="jpeg"):
data = self.get_image()
with MemoryFile() as memfile:
# Change the driver for output
data[1]['driver'] = driver
with MemoryFile() as memfile:
# Change the driver for output
data[1]['driver'] = driver
with memfile.open(**data[1]) as dataset:
dataset.write(data[0])
image = memfile.read()
image = reshape_as_image(image)
im = Image.open(io.BytesIO(image))
b64data = base64.b64encode(im.tobytes()).decode('utf-8')
return b64data
It seems this isn't necessary for some reason, assuming because memfile.read() gives the actual bytes of the image.
def get_image(self, store=False, driver="GTiff"):
data = self.crop_ortho(store)
with MemoryFile() as memfile:
# Change the driver for output
data[1]['driver'] = driver
with memfile.open(**data[1]) as dataset:
dataset.write(data[0])
image = memfile.read()
im = Image.open(io.BytesIO(image))
im = im.convert('RGB')
# Save bytes to a byte array
imgByteArr = io.BytesIO()
im.save(imgByteArr, format='jpeg')
b64data = base64.b64encode(imgByteArr.getvalue())
return b64data
I was trying to extract images from a pdf using PyMuPDF (fitz). My pdf has multiple images in a single page. I am maintaining a proper sequence number while saving my images. I saw that the images being extracted don't follow a proper sequence. Sometimes it is starting to extract from the bottom, sometimes from the top and so on. Is there a way to modify my code so that the extraction follow a proper sequence?
Given below is the code I am using :
import fitz
from PIL import Image
filename = "document.pdf"
doc = fitz.open(filename)
for i in range(len(doc)):
img_num = 0
p_no = 1
for img in doc.getPageImageList(i):
xref = img[0]
pix = fitz.Pixmap(doc, xref)
if pix.n - pix.alpha < 4:
img_num += 1
pix.writeImage("%s-%s.jpg" % (str(p_no),str(img_num)))
else:
img_num += 1
pix1 = fitz.Pixmap(fitz.csRGB, pix)
pix1.writeImage("%s-%s.jpg" % (str(p_no),str(img_num)))
pix1 = None
pix = None
p_no += 1
Given below is a sample page of the pdf
I have the same problem I've used the following code:
import fitz
import io
from PIL import Image
file = "file_path"
pdf_file = fitz.open(file)
for page_index in range(len(pdf_file)):
# get the page itself
page = pdf_file[page_index]
image_list = page.getImageList()
# printing number of images found in this page
if image_list:
print(f"[+] Found {len(image_list)} images in page {page_index}")
else:
print("[!] No images found on the given pdf page", page_index)
for image_index, img in enumerate(page.getImageList(), start=1):
print(img)
print(image_index)
# get the XREF of the image
xref = img[0]
# extract the image bytes
base_image = pdf_file.extractImage(xref)
image_bytes = base_image["image"]
# get the image extension
image_ext = base_image["ext"]
# load it to PIL
image = Image.open(io.BytesIO(image_bytes))
# save it to local disk
image.save(open(f"image{page_index+1}_{image_index}.{image_ext}", "wb"))
The most probable way is to locate the 'img' var and order them.
I'd love to hear any further sggestions or if you found better idea/solution.
Per title, I'm trying to write code to loop through multiple videos in a folder to extract their frames, then write each video's frames to their own new folder, e.g. video1 to frames_video1, video2 to frames_video2.
This is my code:
subclip_video_path = main_path + "\\subclips"
frames_path = main_path + "\\frames"
#loop through videos in file
for subclips in subclip_video_path:
currentVid = cv2.VideoCapture(subclips)
success, image = currentVid.read()
count = 0
while success:
#create new frames folder for each video
newFrameFolder = ("frames_" + subclips)
os.makedirs(newFrameFolder)
I get this error:
[ERROR:0] global C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-k8sx3e60\opencv\modules\videoio\src\cap.cpp (142) cv::VideoCapture::open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.4.0) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-k8sx3e60\opencv\modules\videoio\src\cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): P in function 'cv::icvExtractPattern'
What does this mean? How can I fix this?
You can't loop though string: for subclips in subclip_video_path:
You need to get the list of your videos:
from glob import glob
sub_clip_video_path = glob("sub_clip_video_path/*.mp4")
This means get all the .mp4 extension video files and store it in sub_clip_video_path variable.
My Result:
['sub_clip_video_path/output.mp4', 'sub_clip_video_path/result.mp4']
Since I'm sure the directory contains two .mp4 extension files, now I can continue.
You don't need to re-declare VideoCapture for each frame.
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
success, image = currentVid.read()
count = 0
After you declare VideoCapture read all the frames from the current video, then declare VideoCapture for the next video.
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
.
.
Don't use while success this will create an infinite loop.
If the first frame grabbed from the video, then the success variable returns True. When you say:
while success:
#create new frames folder for each video
newFrameFolder = ("frames_" + subclips)
os.makedirs(newFrameFolder)
You will create infinite amount of folder for the current frame.
Here my result:
import os
import cv2
from glob import glob
sub_clip_video_path = glob("sub_clip_video_path/*.mp4") # Each image extension is `.mp4`
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
success, image = currentVid.read()
if success:
newFrameFolder = "frames_video{}".format(count + 1)
if not os.path.exists(newFrameFolder):
os.makedirs(newFrameFolder)
image_name = os.path.join(newFrameFolder, "frame{}.png".format(image_counter + 1))
cv2.imwrite(image_name, image)
image_counter += 1
else:
break
I gathered all the videos using glob
While the current video is being read:
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
If the current frame successfully grabbed, then declare folder name. If the folder does not exist, create it.
if success:
newFrameFolder = "frames_video{}".format(count + 1)
if not os.path.exists(newFrameFolder):
os.makedirs(newFrameFolder)
Then declare the image name and save it.
image_name = os.path.join(newFrameFolder, "frame{}.png".format(image_counter + 1))
cv2.imwrite(image_name, image)
image_counter += 1
i'm writing a program which takes all the pictures in a given folder and aggregates them into a pdf. The problem I have is that when the images are drawn, they are bigger in size and are rotated to the left oddly. I've searched everywhere, havent found anything even in the reportlab documentation.
Here's the code:
import os
from PIL import Image
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from StringIO import StringIO
def main():
images = image_search()
output = PdfFileWriter()
for image in images:
Image_file = Image.open(image) # need to convert the image to the specific size first.
width, height = Image_file.size
im_width = 1 * cm
# Using ReportLab to insert image into PDF
watermark_str = "watermark" + str(images.index(image)) + '.pdf'
imgDoc = canvas.Canvas(watermark_str)
# Draw image on Canvas and save PDF in buffer
# define the aspect ratio first
aspect = height / float(width)
## Drawing the image
imgDoc.drawImage(image, 0,0, width = im_width, height = (im_width * aspect)) ## at (399,760) with size 160x160
imgDoc.showPage()
imgDoc.save()
# Get the watermark file just created
watermark = PdfFileReader(open(watermark_str, "rb"))
#Get our files ready
pdf1File = open('sample.pdf', 'rb')
page = PdfFileReader(pdf1File).getPage(0)
page.mergePage(watermark.getPage(0))
#Save the result
output.addPage(page)
output.write(file("output.pdf","wb"))
#The function which searches the current directory for image files.
def image_search():
found_images = []
for doc in os.listdir(os.curdir):
image_ext = ['.jpg', '.png', '.PNG', '.jpeg', '.JPG']
for ext in image_ext:
if doc.endswith(ext):
found_images.append(doc)
return found_images
main()
I also tried scaling and specifying the aspect ratio using the im_width variable, which gave the same output.
After a little bit of confusion about your goal I figured out that the goal is to make a PDF overview of the images in the current folder. To do so we actual don't need PyPDF2 as Reportlab offers everything we need for this.
See the code below with the comments as guidelines:
def main():
output_file_loc = "overview.pdf"
imgDoc = canvas.Canvas(output_file_loc)
imgDoc.setPageSize(A4) # This is actually the default page size
document_width, document_height = A4
images = image_search()
for image in images:
# Open the image file to get image dimensions
Image_file = Image.open(image)
image_width, image_height = Image_file.size
image_aspect = image_height / float(image_width)
# Determine the dimensions of the image in the overview
print_width = document_width
print_height = document_width * image_aspect
# Draw the image on the current page
# Note: As reportlab uses bottom left as (0,0) we need to determine the start position by subtracting the
# dimensions of the image from those of the document
imgDoc.drawImage(image, document_width - print_width, document_height - print_height, width=print_width,
height=print_height)
# Inform Reportlab that we want a new page
imgDoc.showPage()
# Save the document
imgDoc.save()