import os import re import shutil import requests import gradio as gr from datetime import datetime from zoneinfo import ZoneInfo from tzlocal import get_localzone TIMEOUT = 15 API = os.getenv("api_tiktok") def timestamp(naive_time: datetime = None, target_tz=ZoneInfo("Asia/Shanghai")): if not naive_time: naive_time = datetime.now() local_tz = get_localzone() aware_local = naive_time.replace(tzinfo=local_tz) return aware_local.astimezone(target_tz).strftime("%Y-%m-%d %H:%M:%S") def download_file(url, video_id, cache_dir="./__pycache__"): if os.path.exists(cache_dir): shutil.rmtree(cache_dir) os.makedirs(cache_dir) local_file = f"{cache_dir}/{video_id}.mp4" response = requests.get(url, stream=True) if response.status_code == 200: with open(local_file, "wb") as file: for chunk in response.iter_content(chunk_size=8192): file.write(chunk) print(f"[{timestamp()}] File was downloaded to {local_file}") return local_file def extract_fst_url(text): url_pattern = r'(https?://[^\s"]+)' match = re.search(url_pattern, text) if match: return match.group(1) else: return None def infer(video_url): video = parse_time = desc = avatar = author = sign = None if not video_url: desc = "The video sharing link is empty!" return video, parse_time, desc, avatar, author, sign video_url = extract_fst_url(video_url) if not video_url: desc = "Please enter a valid video sharing link!" return video, parse_time, desc, avatar, author, sign try: response = requests.get(API, params={"url": video_url}, timeout=TIMEOUT) response_json = response.json() retcode = response_json["code"] if retcode == 200: response_data = response_json["data"] video_id = response_data["play_url"].split("video_id=")[1].split("&")[0] video = download_file(response_data["video_url"], video_id) parse_time = response_data["parse_time"] additional_data = response_data["additional_data"][0] desc = additional_data["desc"] avatar = additional_data["url"].split("?from=")[0] author = additional_data["nickname"] sign = additional_data["signature"] else: desc = f"Interface call failed, error code: HTTP {retcode}" except Exception as e: desc = f"Video parsing failed: {e}" return video, parse_time, desc, avatar, author, sign if __name__ == "__main__": gr.Interface( fn=infer, inputs=[ gr.Textbox( label="Please enter TikTok video sharing short link", placeholder="https://v.douyin.com/*", show_copy_button=True, ), ], outputs=[ gr.Video( label="Video download", show_download_button=True, show_share_button=False, ), gr.Textbox(label="Parsing time", show_copy_button=True), gr.Textbox(label="Video description", show_copy_button=True), gr.Image(label="Author avatar", show_share_button=False), gr.Textbox(label="Author nickname", show_copy_button=True), gr.TextArea(label="Author signature", show_copy_button=True), ], title="Parse TikTok video without watermark", description="This site does not provide any video storage services, only to provide the most basic resolution services", flagging_mode="never", examples=[ "https://v.douyin.com/8FVe5DzarE0", "8.20 Njc:/ K@J.II 11/03 黑塔女士举世无双!# 大黑塔 # 黑塔 # 崩坏星穹铁道 # 再创世的凯歌 # 天才俱乐部 https://v.douyin.com/8FVe5DzarE0/ 复制此链接,打开Dou音搜索,直接观看视频!", ], cache_examples=False, ).launch()