Python Forum
how to correctly set duration of video clips to merge?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
how to correctly set duration of video clips to merge?
#1
Hello I have written a program to create video from audio and two images in the moment. The video with audio can be created, but I don't manage to display the next image as specified in array
photos_start_time = ["00:00", "3:00"] # Times of the image projection start MM:SS.

ramdisk_path set to your local drive in ~/Videos where you have your videos

To test
Specify audio file:
`audio_file = "Groove.mp3"`
Answer if you want to start in current directory (.)
`user_choice = input("...")`
Set the images you want to have in a video.

By default the dirs are set to:
`photos_dir = os.path.join(home_dir, "Stažené")`
`audio_dir = os.path.join(home_dir, "Hudba")`
output_dir = os.path.join(home_dir, "Videa")

Specify fps for your videos here three videos will be generated:
fps_values = [3, 5, 6]
So my question is how to fix it to see every image, right now I see only one image the first one, for all the video duration.

The code:
```
import os
from PIL import Image # Required for checking image dimensions
from moviepy.editor import VideoFileClip, AudioFileClip, concatenate_videoclips, ImageClip
from datetime import datetime

audio_file = "Finance Groove.mp3"

# Getting the user's choice
user_choice = input("Do you want to use the current folder (.) or the default folder? Enter '.' for the current folder or 'default' for the default folder: ")

# Setting the folder path based on the user's choice
if user_choice == '.':
    input_dir = os.path.abspath('.')
    audio_dir = input_dir
else:
    home_dir = os.path.expanduser("~")
    photos_dir = os.path.join(home_dir, "Downloads")
    audio_dir = os.path.join(home_dir, "Music")

output_dir = os.path.join(home_dir, "Videos")

# Convert times from "MM:SS" format to seconds
def time_to_seconds(time_str):
    m, s = map(int, time_str.split(':'))
    return m * 60 + s


def find_duration(photo_times, duration, i):
    if i + 1 < len(photo_times):
        end_time = photo_times[i + 1]
    else:
        end_time = duration
    img_duration = end_time - photo_times[i]
    return img_duration

# File paths
audio_path = os.path.join(audio_dir, audio_file)
# FPS for different versions of the video
fps_values = [3, 5, 6]  # Generate three different videos based on the number of frames
photos = [
    os.path.join(photos_dir, "_527b2337-6f60-4b3e-ae72-a4449dea17e3.jpeg"),
    os.path.join(photos_dir, "dandelions.jpeg")
]
audio_clip = AudioFileClip(audio_path)
duration = audio_clip.duration
ramdisk_size = int(estimate_ramdisk_size(duration, photos, fps_values) / (1024 * 1024))  # MB
audio_clip.close()
create_ramdisk(ramdisk_path, ramdisk_size)  # RAM disk size in MB
photos_start_time = ["00:00", "3:00"]  # Start times in `MM:SS`

# Check if audio file exists
if not os.path.isfile(audio_path):
    print(f"Error: Audio file '{audio_path}' does not exist.")
    os.sys.exit(1)

# Check if images exist
for photo_path in photos:
    if not os.path.isfile(photo_path):
        print(f"Error: Image '{photo_path}' does not exist.")
        os.sys.exit(1)

# Get times in seconds
photo_times = [time_to_seconds(t) for t in photos_start_time]

# Load audio file
audio_clip = AudioFileClip(audio_path)

# Create video clips from photos and different fps
for fps in fps_values:
    print(f"Creating video with FPS = {fps}")

    # Create a list of video clips from photos
    video_clips = []
    for i, photo_path in enumerate(photos):
        dur = find_duration(photo_times, duration, i)
        img_clip = ImageClip(photo_path).set_duration(dur)  # Photo for the entire length of audio
        img_clip = img_clip.set_start(photo_times[i])  # Set photo start
        video_clips.append(img_clip)

    # Concatenate all clips into one video
    final_clip = concatenate_videoclips(video_clips, method="compose")
    final_clip = final_clip.set_audio(audio_clip)
    
    # Set FPS
    final_clip = final_clip.set_duration(duration).fx(lambda clip: clip.set_fps(fps))

    # Temporarily save the final video to RAM disk
    temp_video_path = os.path.join(ramdisk_path, f"temp_video_{fps}.mp4")
    # final_clip.write_videofile(temp_video_path, codec="libx264", audio_codec="aac")
    final_clip.write_videofile(temp_video_path, codec="libx264", audio_codec="aac", threads=2, preset='ultrafast')

    # Close all clips

    audio_clip.close()
    final_clip.close()

    print(f"Video was successfully created and saved to RAM disk at: {ramdisk_path}")

# Concatenate all clips into one video
final_clip = concatenate_videoclips(video_clips, method="compose")
final_clip = final_clip.set_audio(audio_clip)

# Temporarily save the final video to RAM disk
temp_video_path = os.path.join(ramdisk_path, "temp_video.mp4")
final_clip.write_videofile(temp_video_path, codec="libx264", crf="28", audio_codec="aac")

# Close all clips
audio_clip.close()
final_clip.close()

print(f"Video was successfully created and saved to RAM disk at: {ramdisk_path}")

```
Reply
#2
Just to make sure you got current and complete code, not the code which was saved in the file of question. But this will be not translated of sure:

```
import os
from PIL import Image # Je třeba pro kontrolu rozměrů obrázků
from moviepy.editor import VideoFileClip, AudioFileClip, concatenate_videoclips, ImageClip
# from pydub import AudioSegment
from datetime import datetime

audio_file = "Finance Groove.mp3"

# Získání volby uživatele
user_choice = input("Chcete použít aktuální složku (.) nebo přednastavenou složku? Zadejte '.' pro aktuální složku nebo 'default' pro přednastavenou složku: ")

# Nastavení cesty ke složce na základě volby uživatele
if user_choice == '.':
    input_dir = os.path.abspath('.')
    audio_dir = input_dir
else:
    home_dir = os.path.expanduser("~")
    photos_dir = os.path.join(home_dir, "Stažené")
    audio_dir = os.path.join(home_dir, "Hudba")

output_dir = os.path.join(home_dir, "Videa")

# Konverze časů z formátu "HH:MM" na sekundy
def time_to_seconds(time_str):
    m, s = map(int, time_str.split(':'))
    return m * 60 + s

def get_channels(image_path):
    with Image.open(image_path) as img:
        mode = img.mode
        if mode == 'RGB':
            return 3  # 3 kanály
        elif mode == 'RGBA':
            return 4  # 4 kanály
        elif mode == 'L':
            return 1  # 1 kanál
        else:
            raise ValueError(f"Neznámý režim obrázku: {mode}")

def estimate_ramdisk_size(duration, photos, fps_values):
    # Zjistit velikost všech obrázků
    image_sizes = [Image.open(photo).size for photo in photos]
    widths, heights = zip(*image_sizes)  # Oddělení šířek a výšek

    # Zkontrolujte, zda všechny obrázky mají stejné rozměry
    # set() returns count of unique dimensions in list
    if len(set(widths)) != 1 or len(set(heights)) != 1:
        raise ValueError("Všechny obrázky musí mít stejné rozměry.")
    width, height = widths[0], heights[1]
    num_channels = get_channels(photos[0])
    size_per_frame = width * height * num_channels
    total_size = sum(size_per_frame * fps * duration for fps in fps_values)
    compression_factor = 70  # Například 20:1
    compressed_size = total_size / compression_factor
    return compressed_size


# Funkce pro vytvoření RAM disku
def create_ramdisk(ramdisk_path, size_mb):
    if not os.path.exists(ramdisk_path):
        os.makedirs(ramdisk_path)
    size_kb = size_mb * 1024
    with open('ramdisk.log', 'w') as log:
        os.system(f'sudo mount -t tmpfs -o size={size_kb}k tmpfs "{ramdisk_path}"')
        os.system(f'df "{ramdisk_path}" > "ramdisk.log"')
    with open('ramdisk.log', 'r') as log:
        log_content = log.read()
    if ramdisk_path in log_content:
        print(f"RAM disk is correctly mounted at {ramdisk_path}.")
    else:
        print(f"RAM disk is not found")

def find_duration(photo_times, duration, i):
    if i + 1 < len(photo_times):
        end_time = photo_times[i + 1]
    else:
        end_time = duration
    img_duration = end_time - photo_times[i]
    return img_duration

# Vytvoření RAM disku
ramdisk_path = os.path.join(output_dir, "ramdisk")
log_file = os.path.join(output_dir, "ramdisk.log")

# Cesty k souborům
audio_path = os.path.join(audio_dir, audio_file)
# FPS pro různé verze videa
fps_values = [3, 5, 6]  # Vygenerovat tři různá videa podle počtu framů
photos = [
    os.path.join(photos_dir, "_527b2337-6f60-4b3e-ae72-a4449dea17e3.jpeg"),
    os.path.join(photos_dir, "starší žena a muž v lese na procházce pampelišky.jpeg")
]
audio_clip = AudioFileClip(audio_path)
duration = audio_clip.duration
ramdisk_size = int(estimate_ramdisk_size(duration, photos, fps_values) / (1024 * 1024))  # MB
audio_clip.close()
create_ramdisk(ramdisk_path, ramdisk_size)  # Velikost RAM disku v MB
photos_start_time = ["00:00", "3:00"]  # Časy začátku v `HH:MM`

# Kontrola existence audio souboru
if not os.path.isfile(audio_path):
    print(f"Chyba: Audio soubor '{audio_path}' neexistuje.")
    os.sys.exit(1)

# Kontrola existence obrázků
for photo_path in photos:
    if not os.path.isfile(photo_path):
        print(f"Chyba: Obrázek '{photo_path}' neexistuje.")
        os.sys.exit(1)

# Získání časů v sekundách
photo_times = [time_to_seconds(t) for t in photos_start_time]

# Načtení audio souboru
audio_clip = AudioFileClip(audio_path)

# Vytvoření video klipů z fotek a různých fps
for fps in fps_values:
    print(f"Vytváření videa s FPS = {fps}")

    # Vytvoření seznamu video klipů z fotek
    video_clips = []
    for i, photo_path in enumerate(photos):
        dur = find_duration(photo_times, duration, i)
        img_clip = ImageClip(photo_path)
        # img_clip.set_audio(audio_clip)
        if i<len(photos)-1:
           end = photo_times[i+1]-photo_times[i]
        else:
           end = duration - photo_times[i]
        img_clip = img_clip.set_audio(audio_clip.subclip(photo_times[i], end))  # Nastavení audio klipu
        img_clip.set_start(photo_times[i])  # Nastavení začátku fotky
        img_clip.set_duration(end)  # Fotka na vymezený časový úsek
        video_clips.append(img_clip)

    # Sloučení všech klipů do jednoho videa
    final_clip = concatenate_videoclips(video_clips, method="compose")
    final_clip = final_clip.set_audio(audio_clip)
    
    # Nastavení FPS
    final_clip = final_clip.set_duration(duration).fx(lambda clip: clip.set_fps(fps))

    # Dočasné uložení finálního videa na RAM disk
    temp_video_path = os.path.join(ramdisk_path, f"temp_video_{fps}.mp4")
    # final_clip.write_videofile(temp_video_path, codec="libx264", audio_codec="aac")
    final_clip.write_videofile(temp_video_path, codec="libx264", audio_codec="aac", threads=2, preset='ultrafast')

    # Uzavření všech klipů

    audio_clip.close()
    final_clip.close()

    print(f"Video byla úspěšně vytvořena a uložena v RAM disku na adrese: {ramdisk_path}")


# Sloučení všech klipů do jednoho videa
final_clip = concatenate_videoclips(video_clips, method="compose")
final_clip = final_clip.set_audio(audio_clip)

# Dočasné uložení finálního videa na RAM disk
temp_video_path = os.path.join(ramdisk_path, "temp_video.mp4")
final_clip.write_videofile(temp_video_path, codec="libx264", crf="28",audio_codec="aac")

# Uzavření všech klipů
audio_clip.close()
final_clip.close()

print(f"Video byla úspěšně vytvořena a uložena v RAM disku na adrese: {ramdisk_path}")

# Volby pro správu souborů
while True:
    files = os.listdir(ramdisk_path)
    if not files:
        print("Všechny soubory byly smazány nebo přesunuty.")
        break

    print("\nSoubory v RAM disku:")
    for i, file in enumerate(files):
        print(f"{i + 1}: {file}")

    print("\nZadejte číslo souboru pro smazání, 'c' pro kopírování souboru na disk, nebo 'q' pro ukončení:")
    user_input = input("Vaše volba: ").strip()

    if user_input.lower() == 'q':
        break
    elif user_input.lower() == 'c':
        file_index = int(input("Zadejte číslo souboru pro kopírování: ")) - 1
        if 0 <= file_index < len(files):
            new_name = input("Zadejte nové jméno pro soubor (bez přípony): ").strip() + ".mp4"
            src = os.path.join(ramdisk_path, files[file_index])
            dst = os.path.join(output_dir, new_name)
            os.rename(src, dst)
            print(f"Soubor {files[file_index]} byl zkopírován jako {new_name}.")
        else:
            print("Neplatná volba souboru.")
    else:
        try:
            file_index = int(user_input) - 1
            if 0 <= file_index < len(files):
                os.remove(os.path.join(ramdisk_path, files[file_index]))
                print(f"Soubor {files[file_index]} byl smazán.")
            else:
                print("Neplatná volba souboru.")
        except ValueError:
            print("Neplatná volba.")

# Odpojení a smazání RAM disku
os.system(f'sudo umount "{ramdisk_path}"')
os.rmdir(ramdisk_path)

with open(log_file, "a") as log:
    os.system(f'df "{ramdisk_path}" >> "{log_file}"')

print("RAM disk byl odpojen.")
```
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Merge video with subtitles Pavel_47 26 12,382 Jul-06-2022, 02:27 PM
Last Post: Pavel_47
  How to get the duration of AMR audio file using python Prince_Bhatia 0 2,775 Aug-12-2019, 05:58 AM
Last Post: Prince_Bhatia
  Conversion of Time Duration in seconds in python jdevansh99 0 3,367 Jun-05-2018, 05:12 PM
Last Post: jdevansh99
  Extracting clips from Aja Ki Pro FileRecorder underoathed 5 5,272 Nov-19-2017, 04:40 PM
Last Post: nilamo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020