mirror of
https://github.com/sun-guannan/CapCutAPI.git
synced 2025-11-25 03:15:00 +08:00
fix bug and for videolingo
This commit is contained in:
@@ -4,6 +4,7 @@ from create_draft import get_or_create_draft
|
|||||||
from pyJianYingDraft.text_segment import TextBubble, TextEffect
|
from pyJianYingDraft.text_segment import TextBubble, TextEffect
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import requests
|
import requests
|
||||||
|
import os
|
||||||
|
|
||||||
def add_subtitle_impl(
|
def add_subtitle_impl(
|
||||||
srt_path: str,
|
srt_path: str,
|
||||||
@@ -76,8 +77,14 @@ def add_subtitle_impl(
|
|||||||
srt_content = response.text
|
srt_content = response.text
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(f"Failed to download subtitle file: {str(e)}")
|
raise Exception(f"Failed to download subtitle file: {str(e)}")
|
||||||
|
elif os.path.isfile(srt_path): # Check if it's a file
|
||||||
|
try:
|
||||||
|
with open(srt_path, 'r', encoding='utf-8') as f:
|
||||||
|
srt_content = f.read()
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(f"Failed to read local subtitle file: {str(e)}")
|
||||||
else:
|
else:
|
||||||
# If not a URL, use content directly
|
# If not a URL or local file, use content directly
|
||||||
srt_content = srt_path
|
srt_content = srt_path
|
||||||
# Handle possible escape characters
|
# Handle possible escape characters
|
||||||
srt_content = srt_content.replace('\\n', '\n').replace('/n', '\n')
|
srt_content = srt_content.replace('\\n', '\n').replace('/n', '\n')
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ from add_sticker_impl import add_sticker_impl
|
|||||||
from create_draft import create_draft
|
from create_draft import create_draft
|
||||||
from util import generate_draft_url as utilgenerate_draft_url
|
from util import generate_draft_url as utilgenerate_draft_url
|
||||||
|
|
||||||
from settings.local import IS_CAPCUT_ENV, DRAFT_DOMAIN, PREVIEW_ROUTER
|
from settings.local import IS_CAPCUT_ENV, DRAFT_DOMAIN, PREVIEW_ROUTER, PORT
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
@@ -1356,4 +1356,4 @@ def get_video_character_effect_types():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='0.0.0.0', port=9000)
|
app.run(host='0.0.0.0', port=PORT)
|
||||||
@@ -1,20 +1,15 @@
|
|||||||
{
|
{
|
||||||
// Whether it is CapCut international version, default is true
|
|
||||||
"is_capcut_env": true,
|
"is_capcut_env": true,
|
||||||
// API route
|
|
||||||
"draft_domain": "https://www.install-ai-guider.top",
|
"draft_domain": "https://www.install-ai-guider.top",
|
||||||
// Preview route
|
"port": 9001,
|
||||||
"preview_router": "/draft/downloader",
|
"preview_router": "/draft/downloader",
|
||||||
// Whether to upload draft files
|
|
||||||
"is_upload_draft": false,
|
"is_upload_draft": false,
|
||||||
// Configuration for uploading draft files to Alibaba Cloud OSS
|
|
||||||
"oss_config": {
|
"oss_config": {
|
||||||
"bucket_name": "your-bucket-name",
|
"bucket_name": "your-bucket-name",
|
||||||
"access_key_id": "your-access-key-id",
|
"access_key_id": "your-access-key-id",
|
||||||
"access_key_secret": "your-access-key-secret",
|
"access_key_secret": "your-access-key-secret",
|
||||||
"endpoint": "https://your-endpoint.aliyuncs.com"
|
"endpoint": "https://your-endpoint.aliyuncs.com"
|
||||||
},
|
},
|
||||||
// Configuration for uploading rendered MP4 files to Alibaba Cloud OSS
|
|
||||||
"mp4_oss_config": {
|
"mp4_oss_config": {
|
||||||
"bucket_name": "your-mp4-bucket-name",
|
"bucket_name": "your-mp4-bucket-name",
|
||||||
"access_key_id": "your-access-key-id",
|
"access_key_id": "your-access-key-id",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
import requests
|
import requests
|
||||||
|
import shutil
|
||||||
from requests.exceptions import RequestException, Timeout
|
from requests.exceptions import RequestException, Timeout
|
||||||
from urllib.parse import urlparse, unquote
|
from urllib.parse import urlparse, unquote
|
||||||
|
|
||||||
@@ -109,6 +110,27 @@ def download_audio(audio_url, draft_name, material_name):
|
|||||||
raise Exception(f"Failed to download audio:\n{e.stderr}")
|
raise Exception(f"Failed to download audio:\n{e.stderr}")
|
||||||
|
|
||||||
def download_file(url:str, local_filename, max_retries=3, timeout=180):
|
def download_file(url:str, local_filename, max_retries=3, timeout=180):
|
||||||
|
# 检查是否是本地文件路径
|
||||||
|
if os.path.exists(url) and os.path.isfile(url):
|
||||||
|
# 是本地文件,直接复制
|
||||||
|
directory = os.path.dirname(local_filename)
|
||||||
|
|
||||||
|
# 创建目标目录(如果不存在)
|
||||||
|
if directory and not os.path.exists(directory):
|
||||||
|
os.makedirs(directory, exist_ok=True)
|
||||||
|
print(f"Created directory: {directory}")
|
||||||
|
|
||||||
|
print(f"Copying local file: {url} to {local_filename}")
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
# 复制文件
|
||||||
|
shutil.copy2(url, local_filename)
|
||||||
|
|
||||||
|
print(f"Copy completed in {time.time()-start_time:.2f} seconds")
|
||||||
|
print(f"File saved as: {os.path.abspath(local_filename)}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 原有的下载逻辑
|
||||||
# Extract directory part
|
# Extract directory part
|
||||||
directory = os.path.dirname(local_filename)
|
directory = os.path.dirname(local_filename)
|
||||||
|
|
||||||
|
|||||||
@@ -510,6 +510,12 @@ class Script_file:
|
|||||||
lines = srt_content.splitlines()
|
lines = srt_content.splitlines()
|
||||||
|
|
||||||
def __add_text_segment(text: str, t_range: Timerange) -> None:
|
def __add_text_segment(text: str, t_range: Timerange) -> None:
|
||||||
|
fixed_width = -1
|
||||||
|
if self.width < self.height: # 竖屏
|
||||||
|
fixed_width = int(1080 * 0.6)
|
||||||
|
else: # 横屏
|
||||||
|
fixed_width = int(1920 * 0.7)
|
||||||
|
|
||||||
if style_reference:
|
if style_reference:
|
||||||
seg = Text_segment.create_from_template(text, t_range, style_reference)
|
seg = Text_segment.create_from_template(text, t_range, style_reference)
|
||||||
if clip_settings is not None:
|
if clip_settings is not None:
|
||||||
@@ -523,9 +529,12 @@ class Script_file:
|
|||||||
seg.bubble = deepcopy(bubble)
|
seg.bubble = deepcopy(bubble)
|
||||||
if effect:
|
if effect:
|
||||||
seg.effect = deepcopy(effect)
|
seg.effect = deepcopy(effect)
|
||||||
|
# 设置固定宽高
|
||||||
|
seg.fixed_width = fixed_width
|
||||||
else:
|
else:
|
||||||
seg = Text_segment(text, t_range, style=text_style, clip_settings=clip_settings,
|
seg = Text_segment(text, t_range, style=text_style, clip_settings=clip_settings,
|
||||||
border=border, background=background)
|
border=border, background=background,
|
||||||
|
fixed_width=fixed_width)
|
||||||
# 添加气泡和花字效果
|
# 添加气泡和花字效果
|
||||||
if bubble:
|
if bubble:
|
||||||
seg.bubble = deepcopy(bubble)
|
seg.bubble = deepcopy(bubble)
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ def save_draft_background(draft_id, draft_folder, task_id):
|
|||||||
|
|
||||||
logger.info(f"Starting to save draft: {draft_id}")
|
logger.info(f"Starting to save draft: {draft_id}")
|
||||||
# Save draft
|
# Save draft
|
||||||
draft_folder_for_duplicate = draft.Draft_folder("./")
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
draft_folder_for_duplicate = draft.Draft_folder(current_dir)
|
||||||
# Choose different template directory based on configuration
|
# Choose different template directory based on configuration
|
||||||
template_dir = "template" if IS_CAPCUT_ENV else "template_jianying"
|
template_dir = "template" if IS_CAPCUT_ENV else "template_jianying"
|
||||||
draft_folder_for_duplicate.duplicate_as_template(template_dir, draft_id)
|
draft_folder_for_duplicate.duplicate_as_template(template_dir, draft_id)
|
||||||
@@ -108,6 +109,9 @@ def save_draft_background(draft_id, draft_folder, task_id):
|
|||||||
for audio in audios:
|
for audio in audios:
|
||||||
remote_url = audio.remote_url
|
remote_url = audio.remote_url
|
||||||
material_name = audio.material_name
|
material_name = audio.material_name
|
||||||
|
# Use helper function to build path
|
||||||
|
if draft_folder:
|
||||||
|
audio.replace_path = build_asset_path(draft_folder, draft_id, "audio", material_name)
|
||||||
if not remote_url:
|
if not remote_url:
|
||||||
logger.warning(f"Audio file {material_name} has no remote_url, skipping download.")
|
logger.warning(f"Audio file {material_name} has no remote_url, skipping download.")
|
||||||
continue
|
continue
|
||||||
@@ -116,7 +120,7 @@ def save_draft_background(draft_id, draft_folder, task_id):
|
|||||||
download_tasks.append({
|
download_tasks.append({
|
||||||
'type': 'audio',
|
'type': 'audio',
|
||||||
'func': download_file,
|
'func': download_file,
|
||||||
'args': (remote_url, f"{draft_id}/assets/audio/{material_name}"),
|
'args': (remote_url, os.path.join(current_dir, f"{draft_id}/assets/audio/{material_name}")),
|
||||||
'material': audio
|
'material': audio
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -139,7 +143,7 @@ def save_draft_background(draft_id, draft_folder, task_id):
|
|||||||
download_tasks.append({
|
download_tasks.append({
|
||||||
'type': 'image',
|
'type': 'image',
|
||||||
'func': download_file,
|
'func': download_file,
|
||||||
'args': (remote_url, f"{draft_id}/assets/image/{material_name}"),
|
'args': (remote_url, os.path.join(current_dir, f"{draft_id}/assets/image/{material_name}")),
|
||||||
'material': video
|
'material': video
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -155,7 +159,7 @@ def save_draft_background(draft_id, draft_folder, task_id):
|
|||||||
download_tasks.append({
|
download_tasks.append({
|
||||||
'type': 'video',
|
'type': 'video',
|
||||||
'func': download_file,
|
'func': download_file,
|
||||||
'args': (remote_url, f"{draft_id}/assets/video/{material_name}"),
|
'args': (remote_url, os.path.join(current_dir, f"{draft_id}/assets/video/{material_name}")),
|
||||||
'material': video
|
'material': video
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -208,8 +212,8 @@ def save_draft_background(draft_id, draft_folder, task_id):
|
|||||||
update_task_field(task_id, "message", "Saving draft information")
|
update_task_field(task_id, "message", "Saving draft information")
|
||||||
logger.info(f"Task {task_id} progress 70%: Saving draft information.")
|
logger.info(f"Task {task_id} progress 70%: Saving draft information.")
|
||||||
|
|
||||||
script.dump(f"{draft_id}/draft_info.json")
|
script.dump(os.path.join(current_dir, f"{draft_id}/draft_info.json"))
|
||||||
logger.info(f"Draft information has been saved to {draft_id}/draft_info.json.")
|
logger.info(f"Draft information has been saved to {os.path.join(current_dir, draft_id)}/draft_info.json.")
|
||||||
|
|
||||||
draft_url = ""
|
draft_url = ""
|
||||||
# Only upload draft information when IS_UPLOAD_DRAFT is True
|
# Only upload draft information when IS_UPLOAD_DRAFT is True
|
||||||
@@ -221,7 +225,7 @@ def save_draft_background(draft_id, draft_folder, task_id):
|
|||||||
|
|
||||||
# Compress the entire draft directory
|
# Compress the entire draft directory
|
||||||
zip_path = zip_draft(draft_id)
|
zip_path = zip_draft(draft_id)
|
||||||
logger.info(f"Draft directory {draft_id} has been compressed to {zip_path}.")
|
logger.info(f"Draft directory {os.path.join(current_dir, draft_id)} has been compressed to {zip_path}.")
|
||||||
|
|
||||||
# Update task status - Start uploading to OSS
|
# Update task status - Start uploading to OSS
|
||||||
update_task_field(task_id, "progress", 90)
|
update_task_field(task_id, "progress", 90)
|
||||||
@@ -234,9 +238,9 @@ def save_draft_background(draft_id, draft_folder, task_id):
|
|||||||
update_task_field(task_id, "draft_url", draft_url)
|
update_task_field(task_id, "draft_url", draft_url)
|
||||||
|
|
||||||
# Clean up temporary files
|
# Clean up temporary files
|
||||||
if os.path.exists(draft_id):
|
if os.path.exists(os.path.join(current_dir, draft_id)):
|
||||||
shutil.rmtree(draft_id)
|
shutil.rmtree(os.path.join(current_dir, draft_id))
|
||||||
logger.info(f"Cleaned up temporary draft folder: {draft_id}")
|
logger.info(f"Cleaned up temporary draft folder: {os.path.join(current_dir, draft_id)}")
|
||||||
|
|
||||||
|
|
||||||
# Update task status - Completed
|
# Update task status - Completed
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ PREVIEW_ROUTER = "/draft/downloader"
|
|||||||
# 是否上传草稿文件
|
# 是否上传草稿文件
|
||||||
IS_UPLOAD_DRAFT = False
|
IS_UPLOAD_DRAFT = False
|
||||||
|
|
||||||
|
# 端口号
|
||||||
|
PORT = 9000
|
||||||
|
|
||||||
|
OSS_CONFIG = []
|
||||||
|
MP4_OSS_CONFIG=[]
|
||||||
|
|
||||||
# 尝试加载本地配置文件
|
# 尝试加载本地配置文件
|
||||||
if os.path.exists(CONFIG_FILE_PATH):
|
if os.path.exists(CONFIG_FILE_PATH):
|
||||||
try:
|
try:
|
||||||
@@ -34,6 +40,10 @@ if os.path.exists(CONFIG_FILE_PATH):
|
|||||||
if "draft_domain" in local_config:
|
if "draft_domain" in local_config:
|
||||||
DRAFT_DOMAIN = local_config["draft_domain"]
|
DRAFT_DOMAIN = local_config["draft_domain"]
|
||||||
|
|
||||||
|
# 更新端口号配置
|
||||||
|
if "port" in local_config:
|
||||||
|
PORT = local_config["port"]
|
||||||
|
|
||||||
# 更新预览路由
|
# 更新预览路由
|
||||||
if "preview_router" in local_config:
|
if "preview_router" in local_config:
|
||||||
PREVIEW_ROUTER = local_config["preview_router"]
|
PREVIEW_ROUTER = local_config["preview_router"]
|
||||||
|
|||||||
10
util.py
10
util.py
@@ -2,6 +2,7 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
import functools
|
import functools
|
||||||
import time
|
import time
|
||||||
@@ -27,10 +28,13 @@ def is_windows_path(path):
|
|||||||
return re.match(r'^[a-zA-Z]:\\|\\\\', path) is not None
|
return re.match(r'^[a-zA-Z]:\\|\\\\', path) is not None
|
||||||
|
|
||||||
|
|
||||||
def zip_draft(draft_name):
|
def zip_draft(draft_id):
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
# Compress folder
|
# Compress folder
|
||||||
zip_path = f"./tmp/zip/{draft_name}.zip"
|
zip_dir = os.path.join(current_dir, "tmp/zip")
|
||||||
shutil.make_archive(f"./tmp/zip/{draft_name}", 'zip', draft_name)
|
os.makedirs(zip_dir, exist_ok=True)
|
||||||
|
zip_path = os.path.join(zip_dir, f"{draft_id}.zip")
|
||||||
|
shutil.make_archive(os.path.join(zip_dir, draft_id), 'zip', os.path.join(current_dir, draft_id))
|
||||||
return zip_path
|
return zip_path
|
||||||
|
|
||||||
def url_to_hash(url, length=16):
|
def url_to_hash(url, length=16):
|
||||||
|
|||||||
Reference in New Issue
Block a user