Spaces:
Sleeping
Sleeping
import os | |
import requests | |
import time | |
import math | |
import re | |
import shutil | |
import json | |
import subprocess | |
import mimetypes | |
from datetime import datetime, timedelta | |
from moviepy.editor import VideoFileClip | |
import streamlit as st | |
from streamlit_option_menu import option_menu | |
from collections import defaultdict | |
from tqdm import tqdm | |
from googletrans import Translator | |
from bs4 import BeautifulSoup | |
def format_number(number): | |
if number < 1000: | |
return str(number) | |
elif number < 1000000: | |
return f"{round(number / 1000)} ribu" | |
elif number < 1000000000: | |
return f"{round(number / 1000000)} juta" | |
else: | |
return f"{round(number / 1000000000)} miliar" | |
def cut_video(filename, judul_video, start_time, end_time): | |
start_time_parts = start_time.split(':') | |
end_time_parts = end_time.split(':') | |
start_time_seconds = int(start_time_parts[0]) * 3600 + int(start_time_parts[1]) * 60 + float(start_time_parts[2]) | |
end_time_seconds = int(end_time_parts[0]) * 3600 + int(end_time_parts[1]) * 60 + float(end_time_parts[2]) | |
potong = "/home/user/app/Hasil Potong" | |
if not os.path.exists(potong): | |
os.makedirs(potong) | |
output_file_path = f'{potong}/{judul_video}.mp4' | |
with VideoFileClip(filename) as video: | |
subclip = video.subclip(start_time_seconds, end_time_seconds) | |
subclip.write_videofile(output_file_path) | |
return output_file_path | |
def session(video_info, video_file, thumbnail_file, choice): | |
st.session_state.video_info = video_info | |
st.session_state.video_file = video_file | |
st.session_state.thumbnail_file = thumbnail_file | |
if choice: | |
hasil = "Hasil Potongan" | |
elif choice: | |
hasil = "Hasil Compress" | |
else: | |
hasil = "" | |
if 'video_info' in st.session_state: | |
num_lines = st.session_state.video_info.count('\n') + 1 | |
text_area_height = 25 * num_lines | |
st.text_area("Informasi Video", st.session_state.video_info, height=text_area_height) | |
if video_file != '': | |
st.image(st.session_state.thumbnail_file) | |
st.video(st.session_state.video_file) | |
with open(st.session_state.video_file, 'rb') as f: | |
file_contents = f.read() | |
st.download_button( | |
label=f"Download {hasil} Video", | |
data=file_contents, | |
file_name=st.session_state.video_file.split("/")[-1].title().replace('Mp4', 'mp4'), | |
mime='video/mp4' | |
) | |
def convert_size(size_bytes): | |
units = ["B", "KB", "MB", "GB", "TB"] | |
index = 0 | |
while size_bytes >= 1024 and index < len(units) - 1: | |
size_bytes /= 1024 | |
index += 1 | |
return f"{size_bytes:.2f} {units[index]}" | |
def add_space(name): | |
new_name = '' | |
for i in range(len(name)): | |
if i > 0 and name[i].isupper() and name[i-1].islower(): | |
new_name += ' ' | |
new_name += name[i] | |
return new_name | |
def download_file(url, new_name, directory): | |
headers = { | |
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3" | |
} | |
response = requests.get(url, stream=True, headers=headers) | |
content_type = response.headers.get("Content-Type") | |
extension = mimetypes.guess_extension(content_type) | |
file_name = new_name + extension | |
if not os.path.exists(directory): | |
os.makedirs(directory) | |
filename = f"{directory}/{file_name}" | |
with open(filename, 'wb') as file: | |
total_size = int(response.headers.get("Content-Length", 0)) | |
progress_bar = tqdm(total=total_size, unit="B", unit_scale=True, ncols=80) | |
for chunk in response.iter_content(chunk_size=1024): | |
if chunk: | |
file.write(chunk) | |
progress_bar.update(len(chunk)) | |
progress_bar.close() | |
return filename | |
def convert_japanese_to_romaji(text): | |
translator = Translator(service_urls=['translate.google.com']) | |
translation = translator.translate(text, src='ja', dest='ja') | |
return translation.pronunciation | |
def translate_japanese_to_english(text): | |
translator = Translator(service_urls=['translate.google.com']) | |
translation = translator.translate(text, src='ja', dest='en') | |
return translation.text | |
def get_video_resolution(input_file): | |
command = ['ffprobe', '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=width,height', '-of', 'json', input_file] | |
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
if result.returncode == 0: | |
video_info = json.loads(result.stdout) | |
width = video_info['streams'][0]['width'] | |
height = video_info['streams'][0]['height'] | |
return (width, height) | |
else: | |
print(f'Error getting video resolution: {result.stderr}') | |
return None | |
def get_video_info(url): | |
response = requests.get(url) | |
soup = BeautifulSoup(response.text, 'html.parser') | |
# Mencari judul video di elemen meta dengan name="twitter:title" | |
title = soup.find("meta", attrs={"name": "twitter:title"}) | |
if title: | |
video_title = title['content'] | |
# Hapus semua karakter yang terdapat di dalam kurung siku (termasuk angka) | |
video_title = re.sub(r'\[[^\]]*\]', '', video_title) | |
# Hapus kata 'Cosplay ' | |
video_title = video_title.replace('Cosplay ', '') | |
# Tukar posisi kalimat yang dipisahkan oleh ' - ' | |
if ' - ' in video_title: | |
parts = video_title.split(' - ') | |
video_title = f"{parts[1]} - {parts[0]}" | |
actress = parts[0].lstrip() | |
series = parts[1].lstrip() | |
else: | |
actress = '' | |
series = '' | |
# Ubah dua spasi menjadi satu spasi | |
video_title = re.sub(r'\s{2,}', '', video_title) | |
print(f"Artis: {actress} dan Series: {series}") | |
# Mencari ThumbnailUrl di elemen meta dengan name="twitter:image" | |
thumbnail = soup.find("meta", attrs={"name": "twitter:image"}) | |
if thumbnail: | |
thumbnail_url = thumbnail['content'] | |
# Mencari VideoUrl | |
script_tag = soup.find('script', type='application/ld+json') | |
data = json.loads(script_tag.string) | |
selected_video_url = None | |
for item in data['@graph']: | |
if item['@type'] == 'VideoObject': | |
selected_video_url = item['contentURL'] | |
# Mencari Digits | |
if series == 'Cospuri': | |
# Extract digits from thumbnail_url | |
match = re.search(r'/0(\d{3})', thumbnail_url) | |
if match: | |
digits = match.group(1) | |
elif series == 'Fellatio Japan': | |
# Extract digits from thumbnail_url | |
match = re.search(r'/(\d+)_', thumbnail_url) | |
if match: | |
digits = match.group(1) | |
return actress, series, digits, selected_video_url, thumbnail_url | |
def find_image_file(name, directory): | |
for root, dirs, files in os.walk(directory): | |
for file in files: | |
if file == f'{name}.jpg': | |
return os.path.join(root, file) | |
return None | |
def extract_number(video_file): | |
# Use a regular expression to find the first group of digits in the video file name | |
match = re.search(r'\d+', video_file) | |
if match: | |
# If a group of digits is found, return it as an integer | |
return int(match.group()) | |
else: | |
# If no group of digits is found, return a large number to ensure that this video file is processed last | |
return float('inf') | |
def get_video_resolution(input_file): | |
command = ['ffprobe', '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=width,height', '-of', 'json', input_file] | |
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
if result.returncode == 0: | |
video_info = json.loads(result.stdout) | |
width = video_info['streams'][0]['width'] | |
height = video_info['streams'][0]['height'] | |
return (width, height) | |
else: | |
print(f'Error getting video resolution: {result.stderr}') | |
return None | |
def convert_videos(height, filename): | |
download_folder = os.path.dirname(filename) | |
konversi_folder = '/home/user/app/Hasil Konversi' | |
if not os.path.exists(konversi_folder): | |
os.makedirs(konversi_folder) | |
video_extensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv', '.webm', '.mpeg', '.3gp', '.m4v', '.mpg', '.vob', '.ts', '.asf', '.rm', '.swf', '.ogv'] | |
for file in os.listdir(download_folder): | |
file_extension = os.path.splitext(file)[1].lower() | |
if file_extension in video_extensions: | |
input_file = os.path.join(download_folder, file) | |
output_file = os.path.join(konversi_folder, file) | |
# Get the original width and height of the video using ffprobe | |
resolution = get_video_resolution(input_file) | |
if resolution is not None: | |
width_ori, height_ori = resolution | |
# Calculate the width/height for conversion using the formula | |
if (height_ori < width_ori): | |
width = int((width_ori / height_ori) * height) | |
if (width_ori / height_ori) * height % 1 != 0: | |
width += 1 | |
# Convert video using ffmpeg | |
if height == 720: | |
# command = f'ffmpeg -i "{input_file}" -s {width}x{height} -b:v 850k -bufsize 1000k -r 30 -b:a 160k -ar 44100 -ac 2 "{output_file}"' | |
command = f'ffmpeg -i "{input_file}" -s {width}x{height} -b:v 1350k -bufsize 1500k -r 30 -b:a 160k -ar 48000 -ac 2 "{output_file}"' | |
elif height == 480: | |
command = f'ffmpeg -i "{input_file}" -s {width}x{height} -b:v 600k -bufsize 700k -r 24 -b:a 95k -ar 44100 -ac 2 "{output_file}"' | |
elif height == 360: | |
command = f'ffmpeg -i "{input_file}" -s {width}x{height} -b:v 250k -bufsize 300k -r 24 -b:a 50k -ar 44100 -ac 2 "{output_file}"' | |
else: | |
width = height | |
height = int((height_ori / width_ori) * width) | |
if (height_ori / width_ori) * width % 1 != 0: | |
height += 1 | |
# Convert video using ffmpeg | |
if width == 720: | |
# command = f'ffmpeg -i "{input_file}" -s {width}x{height} -b:v 850k -bufsize 1000k -r 30 -b:a 160k -ar 44100 -ac 2 "{output_file}"' | |
command = f'ffmpeg -i "{input_file}" -s {width}x{height} -b:v 1350k -bufsize 1500k -r 30 -b:a 160k -ar 48000 -ac 2 "{output_file}"' | |
elif width == 480: | |
command = f'ffmpeg -i "{input_file}" -s {width}x{height} -b:v 600k -bufsize 700k -r 24 -b:a 95k -ar 44100 -ac 2 "{output_file}"' | |
os.system(command) | |
return output_file | |
def join_video(name, thumbnail_file, video_file): | |
output_dir = '/home/user/app/Hasil Join' | |
if not os.path.exists(output_dir): | |
os.makedirs(output_dir) | |
# Tentukan jalur ke file audio yang akan digunakan untuk intro | |
audio_file = 'sound.wav' | |
# Tentukan jalur ke file output | |
output_file = f'{output_dir}/{name}.mp4' | |
# Gunakan ffmpeg untuk membuat video 1 detik dari file gambar dan audio | |
subprocess.run(['ffmpeg', '-loop', '1', '-i', thumbnail_file, '-i', audio_file, '-c:v', 'libx264', '-b:v', '850k', '-bufsize', '1000k', '-r', '30', '-b:a', '160k', '-ar', '44100', '-ac', '2', '-t', '1', '-pix_fmt', 'yuv420p', '-vf', 'scale=1280:720','-shortest', f'{name}.mp4']) | |
# Gunakan ffmpeg untuk menggabungkan intro dan video | |
with open('input.txt', 'w') as f: | |
f.write(f"file '{name}.mp4'\n") | |
f.write(f"file '{video_file}'\n") | |
subprocess.run(['ffmpeg','-f','concat','-safe','0','-i','input.txt','-c:v','libx264','-b:v','850k','-bufsize','1000k','-r','30','-b:a','160k','-ar','44100','-ac','2','-c:a','aac','-pix_fmt','yuv420p','-vf','scale=1280:720', output_file]) | |
return output_file |