Cutter / app.py
salomonsky's picture
Update app.py
315381c
import os
import zipfile
import random
import base64
from others import *
import streamlit as st
from io import BytesIO
from moviepy.editor import vfx
from streamlit_option_menu import option_menu
from youtube import youtube, download_youtube
from moviepy.video.io.VideoFileClip import VideoFileClip
def session(info_list):
st.video(info_list[1])
st.text(f"Video Information: {info_list[0]}")
if len(info_list) == 5:
st.text(f"Duration: {info_list[3]} - {info_list[4]} seconds")
def random_cuts(video_file, title, num_cuts=1, duration=60, speed_factor=1.0, mute_audio=False, use_aspect_ratio=None):
clip = VideoFileClip(video_file)
total_duration = clip.duration
cuts = []
for _ in range(num_cuts):
start_time = random.uniform(0, max(total_duration - duration, 0))
end_time = min(start_time + duration, total_duration)
cuts.append((start_time, end_time))
output_files = []
prev_end_time = 0
for i, (start_time, end_time) in enumerate(cuts):
if start_time == prev_end_time:
continue
output_file = f"{title}_cut_{i+1}.mp4"
clipped_clip = clip.subclip(start_time, end_time)
if mute_audio:
clipped_clip = clipped_clip.set_audio(None)
clipped_clip = clipped_clip.fx(vfx.speedx, speed_factor)
if use_aspect_ratio:
original_width, original_height = clip.size
if use_aspect_ratio == '16:9':
target_ratio = 16 / 9
elif use_aspect_ratio == '9:16':
target_ratio = 9 / 16
elif use_aspect_ratio == '21:9':
target_ratio = 21 / 9
else:
target_ratio = 16 / 9
if use_aspect_ratio:
original_width, original_height = clip.size
if use_aspect_ratio == '21:9':
target_ratio = 21 / 9
else:
target_ratio = 16 / 9 if use_aspect_ratio == '16:9' else 9 / 16
target_width = int(original_height * target_ratio)
target_height = original_height
if use_aspect_ratio == '21:9':
target_height = int(original_width / target_ratio)
margin = (original_height - target_height) // 2
clipped_clip = clipped_clip.crop(y1=margin, y2=original_height - margin)
else:
margin = (original_width - target_width) // 2
clipped_clip = clipped_clip.crop(x1=margin, x2=original_width - margin)
with st.spinner(f'Procesando video {i+1} de {num_cuts}...'):
clipped_clip.write_videofile(output_file, codec="libx264", audio_codec="aac", verbose=False)
output_files.append(output_file)
prev_end_time = end_time
return output_files, cuts
def download_all_button(cut_files):
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
for cut_file in cut_files:
zip_file.write(cut_file, os.path.basename(cut_file))
zip_filename = 'cortes_videos.zip'
zip_data = zip_buffer.getvalue()
b64 = base64.b64encode(zip_data).decode()
href = f'<a href="data:application/zip;base64,{b64}" download="{zip_filename}">Descargar Todos</a>'
st.markdown(href, unsafe_allow_html=True)
opciones = ['YouTube']
with st.sidebar:
seleccionado = option_menu("Descargador", opciones, icons=['play'], menu_icon="cast", default_index=0)
funciones = [youtube]
if seleccionado:
indice = opciones.index(seleccionado)
funcion = funciones[indice]
st.title(f"{seleccionado} Descargador de Videos")
st.write(f"Descarga y corta una parte aleatoria de {seleccionado}.")
video_link = st.text_input("Enlace del Video", value='https://www.youtube.com/watch?v=urhsbKIF9pE')
aspect_ratio_options = ['16:9', '9:16', '21:9']
aspect_ratio_choice = st.selectbox('Seleccionar Proporción:', aspect_ratio_options, index=2)
resolution_options = [144, 240, 360, 720]
resolution_choice = st.selectbox('Seleccionar Resolución:', resolution_options, index=2)
choice = st.radio('Seleccionar Proceso:', ['Cortar Video', 'Descargar Completo'], 1)
if choice == 'Cortar Video':
num_cuts = st.slider('Seleccionar número de cortes', 1, 10, 1)
duration_minutes_slider = st.slider('Seleccionar duración de los cortes (minutos)', 1, 180, 1)
duration_seconds = duration_minutes_slider * 60
speed_factor = st.slider('Seleccionar velocidad del video', -2.0, 3.0, 1.0)
mute_audio = st.checkbox('Eliminar sonido de los videos cortados')
if st.button(f"Descargar y Cortar {seleccionado}"):
video_file, titulo_video, video_info, thumbnail_file = funcion(video_link, resolusi_input=resolution_choice)
cut_files, cuts = random_cuts(video_file, titulo_video, num_cuts=num_cuts, duration=duration_seconds, speed_factor=speed_factor, mute_audio=mute_audio, use_aspect_ratio=aspect_ratio_choice)
for i, cut_file in enumerate(cut_files):
file_size = os.path.getsize(cut_file)
info_list = [f"{titulo_video}_cut_{i+1}", cut_file, thumbnail_file, cuts[i][0], cuts[i][1]]
session(info_list)
download_all_button(cut_files)