0

I have a script that combines a background and a sentence into 1 image and then creates a 10second clip from just that image. However, even though the images get created correctly, about 20% of the created clips are corrupted. Here is the code I used:

file = open(f"quotes/{genre}.json")
    quotes = json.load(file)

    # Create a TEMP folder to save the images
    os.mkdir("clips")

    clips = list()
    for i in range(imagesNeeded):
        # Get quote, background and font
        quote = random.choice(quotes)
        background = random.choice(os.listdir(f"./backgrounds/{genre}"))
        font = random.choice(os.listdir(f"./fonts"))

        #Video size 1920x1080 16:9
        # Open image and resize to ratio
        image = Image.open(f'./backgrounds/{genre}/{background}')
        image_editable = ImageDraw.Draw(image)

        #resize quote so it will fit the image
        font_size = 200
        new_quote, width, height = resizequote(quote, image, font_size)

        title_font = ImageFont.truetype(f"./fonts/{font}", font_size)
        w, h = image_editable.textsize(new_quote,font=title_font)
        
        image_editable.text((0.5*(width-w),0.5*(height-h)), new_quote, (255, 255, 255), font=title_font)

        #Create the clip
        numpydata = asarray(image)
        clip = ImageClip(numpydata).set_duration(10)
        filename = ''.join(random.choice([chr(i) for i in range(ord('a'),ord('z'))]) for _ in range(20))
        clip.write_videofile(f"clips/{filename}.mp4", fps=24, threads=8)
        print(f"Background: {background}")
        print(f"Quote: {quote}")
        print(f"Font: {font}")
        
        clips.append(clip)
        print(f"Created {i} clips")

For the font I use .ttf files. I have tried just using 1 single ttf file and that still gave some corrupt files, so I have concluded that that could not be the issue. All the backgrounds used in this are .jpg files and all the quotes are just strings stored in the JSON file. I have before tried saving every image and still get the same behaviour from the ImageClip() function.

Is there anything in my function that could cause this? Or is there a workaround for it? I would even use a different library to create the clips and preferrably also concatenate them into one video.

Thomas Smeman
  • 175
  • 11
  • 1
    Your code is too cluttered, but (1) am I correct that the only part matters are the lines after `#Create the clip`? (2) If so, what is the dimension of `numpydata` and it's pixel format (rgb24)? (3) Also, have you looked at the images itself and made sure they appear correct in say `matplotlib`? (4) Consider edit your post to only include the troubling part. – kesh Feb 20 '22 at 23:14

1 Answers1

-1
def create_video(genre, audioLength, audio):
    imagesNeeded = math.ceil(audioLength/10)
    print(f"Creating {imagesNeeded} clips")

    file = open(f"quotes/{genre}.json")
    quotes = json.load(file)

    # Create a TEMP folder to save the images
    os.mkdir("clips")

    clips = list()
    for i in range(imagesNeeded):
        # Get quote, background and font
        quote = random.choice(quotes)
        background = random.choice(os.listdir(f"./backgrounds/{genre}"))
        font = random.choice(os.listdir(f"./fonts"))

        #Video size 1920x1080 16:9
        # Open image and resize to ratio
        image = Image.open(f'./backgrounds/{genre}/{background}')
        image_editable = ImageDraw.Draw(image)

        #resize quote so it will fit the image
        font_size = 200
        new_quote, width, height = resizequote(quote, image, font_size)

        title_font = ImageFont.truetype(f"./fonts/{font}", font_size)
        w, h = image_editable.textsize(new_quote,font=title_font)
        
        image_editable.text((0.5*(width-w),0.5*(height-h)), new_quote, (255, 255, 255), font=title_font)

        #Create the clip
        numpydata = asarray(image)
        clip = ImageClip(numpydata).set_duration(10).resize( (1920,1080) )
        filename = ''.join(random.choice([chr(i) for i in range(ord('a'),ord('z'))]) for _ in range(15))
        clip.write_videofile(f"clips/{filename}.mp4", fps=24, threads=8)
        
        clips.append(clip)
        print(f"Created {i} clips")

The code above works and is very fast. I used the resize() method, which makes me able to compose everything together very fast. I also found that some of the backgrounds I used consistently generated corrupted clips. Why that is I do not know, but after deleting them it works.

Thomas Smeman
  • 175
  • 11