1

I'm reading a video from YouTube(for testing purpose. real case would be from a video camera feed) and take each frame and inject a logo on it and create another video using those frames. Also I need to save these frames as images as well(which is already works for me). I tried the following,

img = cv2.imread('logo.png')
img_height, img_width, _ = img.shape
url = "https://www.youtube.com/watch?v=vDHtypVwbHQ"
video = pafy.new(url)
best = video.getbest(preftype="mp4")
frame_no = 1

width = 1280
hieght = 720
fps = 30
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
videoW = cv2.VideoWriter('image_to_video.mp4', fourcc, float(fps), (width, hieght))

while True:
    _, frame = video.read()
    frame[y:y + img_height , x:x + img_width ] = img          
    videoW.write(frame)
    frame_no += 1

This writes a video but it says the video corrupted or incorrect extension. What would be the best way to write these frames into a new video in Python with OpenCV?

6
  • I see a TYPO, in the initial part you indicate that the pafy object is assigned to the video variable: video = pafy.new(url), and then you assign the videowriter object to that same variable: video = cv2.VideoWriter(. On the other hand VideoWriter serves to write, and instead you try to read from that file. Finally, why do you use pafy if in the end "best" you don't use it at all? Commented Oct 23, 2021 at 5:27
  • Yes. It was a TYPO when I was pasting the code. I've updated the code. Commented Oct 23, 2021 at 5:30
  • Also the read method returns a tuple where the first one indicates if the operation was executed correctly so it is better to check: ret, frame = video.read() if ret: # foo process Commented Oct 23, 2021 at 5:30
  • This is checking the pafy docs and I can't find any read method, so _, frame = video.read() should throw an exception to you, pointing out that you are using a non-existent method. Commented Oct 23, 2021 at 5:33
  • Given the errors you indicate, I think that as soon as _, frame = video.read() is executed, the program breaks and there will only be an empty .mp4 so you cannot reproduce it. Commented Oct 23, 2021 at 5:34

1 Answer 1

1

There are many illogical things in the implementation such as "video" is a pafy.Stream that does not have a read method.

What you should do use the Stream url together with VideoCapture to obtain the frames, copy the pixels of the logo, and write it with VideoWriter.

import cv2
import pafy


def apply_logo(url, logo, filename):
    video = pafy.new(url)
    best = video.getbest(preftype="mp4")
    reader = cv2.VideoCapture(best.url)
    if not reader.isOpened():
        return False

    fourcc = cv2.VideoWriter_fourcc(*"MP4V")
    writer = cv2.VideoWriter(filename, fourcc, 60.0, best.dimensions)

    logo_width, logo_height = [min(x, y) for x, y in zip(best.dimensions, logo.shape)]

    i = 0
    while True:
        ret, frame = reader.read()
        if ret:
            frame[:logo_width, :logo_height] = logo[:logo_width, :logo_height]
            writer.write(frame)
            i += 1
            print(i)
        else:
            break

    reader.release()
    writer.release()
    return True

url = "https://www.youtube.com/watch?v=vDHtypVwbHQ"
logo = cv2.imread("logo.png")
apply_logo(url, logo, "output.mp4")
Sign up to request clarification or add additional context in comments.

2 Comments

Works as expected. Thanks for saving my day
the release() call on the VideoWriter object is important. don't just post a solution they can copy and learn nothing from.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.