Neon-AI commited on
Commit
cadcb1f
·
verified ·
1 Parent(s): a12fcb7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -43
app.py CHANGED
@@ -1,7 +1,6 @@
1
  import requests
2
  import tempfile
3
  import os
4
- import shutil
5
  import subprocess
6
  from fastapi import FastAPI, BackgroundTasks
7
  from pydantic import BaseModel
@@ -10,7 +9,6 @@ import re
10
 
11
  app = FastAPI(title="Neon Anime Blur & Upload")
12
 
13
- # Constants
14
  UPLOAD_URL = "https://0x0.st"
15
  RENDER_UPDATE_ENDPOINT = "https://nt-anime-api.onrender.com/update"
16
  HF_AYANO_BASE = "https://a-y-a-n-o-k-o-j-i-dnd-api.hf.space"
@@ -18,11 +16,8 @@ HF_AYANO_BASE = "https://a-y-a-n-o-k-o-j-i-dnd-api.hf.space"
18
  QUALITIES = ["360p", "720p", "1080p"]
19
  queue_lock = Lock()
20
 
21
- def log_error(msg: str):
22
- print(f"[HF ERROR] {msg}", flush=True)
23
-
24
- class EpisodeExceedsAvailableCount(Exception):
25
- pass
26
 
27
  class StartPayload(BaseModel):
28
  anime_id: str
@@ -30,6 +25,7 @@ class StartPayload(BaseModel):
30
 
31
  def download_video(anime_id: str, episode: int, quality: str) -> str | None:
32
  url = f"{HF_AYANO_BASE}/anime/download?id={anime_id}&episode={episode}&quality={quality}"
 
33
  try:
34
  resp = requests.get(url, timeout=20)
35
  resp.raise_for_status()
@@ -38,19 +34,21 @@ def download_video(anime_id: str, episode: int, quality: str) -> str | None:
38
  return None
39
  video_url = data["direct_link"]
40
  except:
 
41
  return None
42
 
43
- headers = {"User-Agent": "Mozilla/5.0 Chrome/120.0", "Referer": "https://animepahe.si/"}
44
  tmp_path = tempfile.mktemp(suffix=".mp4")
 
45
  try:
46
  with requests.get(video_url, headers=headers, stream=True, timeout=120) as r:
47
  r.raise_for_status()
48
  with open(tmp_path, "wb") as f:
49
- for chunk in r.iter_content(chunk_size=8192):
50
- f.write(chunk)
51
  return tmp_path
52
- except Exception as e:
53
- log_error(f"Download failed: {e}")
54
  if os.path.exists(tmp_path):
55
  os.remove(tmp_path)
56
  return None
@@ -60,13 +58,16 @@ def get_filename(anime_name: str, ep: int, quality: str) -> str:
60
  return f"nt-animes_{slug}_ep{ep}_{quality}.mp4"
61
 
62
  def upload_to_0x0(file_path: str, file_name: str) -> str:
 
63
  try:
64
  with open(file_path, "rb") as f:
65
  r = requests.post(UPLOAD_URL, files={"file": (file_name, f)}, timeout=180)
66
  r.raise_for_status()
67
- return r.text.strip()
 
 
68
  except Exception as e:
69
- log_error(f"0x0 upload failed: {e}")
70
  raise
71
 
72
  def notify_render(anime_id: str, episode: int, quality: str, file_url: str, file_name: str, status: int):
@@ -78,45 +79,34 @@ def notify_render(anime_id: str, episode: int, quality: str, file_url: str, file
78
  "file_name": file_name,
79
  "status": status
80
  }
 
81
  try:
82
  requests.post(RENDER_UPDATE_ENDPOINT, json=payload, timeout=10)
83
  except Exception as e:
84
- log_error(f"Notify failed: {e}")
85
-
86
- BLUR_W = 74
87
- BLUR_H = 17
88
- TEXT = "nt-animes"
89
- FONT_COLOR = "white"
90
- FONT_SIZE = 12
91
- TEXT_X = 8
92
- TEXT_Y = 8
93
 
94
  def blur_video(input_path: str) -> str:
95
  output = tempfile.mktemp(suffix="_blurred.mp4")
96
  filter_graph = (
97
- f"[0:v]crop={BLUR_W}:{BLUR_H}:0:0,boxblur=luma_radius=4:luma_power=1:chroma_radius=0[top];"
98
- f"[0:v][top]overlay=0:0,"
99
- f"drawtext=text={TEXT}:x={TEXT_X}:y={TEXT_Y}:fontcolor={FONT_COLOR}:fontsize={FONT_SIZE}[v]"
100
  )
101
  cmd = [
102
  "ffmpeg", "-y", "-i", input_path,
103
  "-filter_complex", filter_graph,
104
- "-map", "[v]",
105
- "-map", "0:a?",
106
- "-c:v", "libx264",
107
- "-preset", "ultrafast",
108
- "-crf", "23",
109
- "-c:a", "copy",
110
- output
111
  ]
112
  try:
113
  subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
114
  return output
115
  except Exception as e:
116
- log_error(f"Blur failed: {e}")
117
  raise
118
 
119
  def process_anime(anime_id: str, anime_name: str):
 
120
  episode = 1
121
  while True:
122
  episode_processed = False
@@ -125,26 +115,31 @@ def process_anime(anime_id: str, anime_name: str):
125
  local_file = download_video(anime_id, episode, quality)
126
  if not local_file:
127
  continue
 
 
128
  blurred_file = blur_video(local_file)
129
  os.remove(local_file)
 
130
  file_name = get_filename(anime_name, episode, quality)
131
  file_url = upload_to_0x0(blurred_file, file_name)
132
  os.remove(blurred_file)
 
133
  notify_render(anime_id, episode, quality, file_url, file_name, 2)
134
  episode_processed = True
135
- except EpisodeExceedsAvailableCount:
136
- notify_render(anime_id, episode, "", "", "", 5)
137
- return
138
- except Exception as e:
139
- log_error(f"Error ep{episode} {quality}: {e}")
140
  notify_render(anime_id, episode, quality, "", "", 3)
 
141
  if not episode_processed:
142
- notify_render(anime_id, 0, "", "", "", 5) # complete
 
143
  break
144
  episode += 1
 
145
 
146
  @app.post("/start")
147
- def start_endpoint(payload: StartPayload, background_tasks: BackgroundTasks):
 
148
  with queue_lock:
149
- background_tasks.add_task(process_anime, payload.anime_id, payload.anime_name)
150
- return {"code": 4, "message": "Job queued and processing in background"}
 
1
  import requests
2
  import tempfile
3
  import os
 
4
  import subprocess
5
  from fastapi import FastAPI, BackgroundTasks
6
  from pydantic import BaseModel
 
9
 
10
  app = FastAPI(title="Neon Anime Blur & Upload")
11
 
 
12
  UPLOAD_URL = "https://0x0.st"
13
  RENDER_UPDATE_ENDPOINT = "https://nt-anime-api.onrender.com/update"
14
  HF_AYANO_BASE = "https://a-y-a-n-o-k-o-j-i-dnd-api.hf.space"
 
16
  QUALITIES = ["360p", "720p", "1080p"]
17
  queue_lock = Lock()
18
 
19
+ def log(msg: str):
20
+ print(f"[HF] {msg}", flush=True)
 
 
 
21
 
22
  class StartPayload(BaseModel):
23
  anime_id: str
 
25
 
26
  def download_video(anime_id: str, episode: int, quality: str) -> str | None:
27
  url = f"{HF_AYANO_BASE}/anime/download?id={anime_id}&episode={episode}&quality={quality}"
28
+ log(f"Fetching link for ep {episode} {quality}")
29
  try:
30
  resp = requests.get(url, timeout=20)
31
  resp.raise_for_status()
 
34
  return None
35
  video_url = data["direct_link"]
36
  except:
37
+ log(f"Failed to get link ep {episode} {quality}")
38
  return None
39
 
40
+ headers = {"User-Agent": "Mozilla/5.0", "Referer": "https://animepahe.si/"}
41
  tmp_path = tempfile.mktemp(suffix=".mp4")
42
+ log(f"Downloading ep {episode} {quality}")
43
  try:
44
  with requests.get(video_url, headers=headers, stream=True, timeout=120) as r:
45
  r.raise_for_status()
46
  with open(tmp_path, "wb") as f:
47
+ shutil.copyfileobj(r.raw, f)
48
+ log(f"Downloaded ep {episode} {quality}")
49
  return tmp_path
50
+ except:
51
+ log(f"Download failed ep {episode} {quality}")
52
  if os.path.exists(tmp_path):
53
  os.remove(tmp_path)
54
  return None
 
58
  return f"nt-animes_{slug}_ep{ep}_{quality}.mp4"
59
 
60
  def upload_to_0x0(file_path: str, file_name: str) -> str:
61
+ log(f"Uploading {file_name}")
62
  try:
63
  with open(file_path, "rb") as f:
64
  r = requests.post(UPLOAD_URL, files={"file": (file_name, f)}, timeout=180)
65
  r.raise_for_status()
66
+ url = r.text.strip()
67
+ log(f"Uploaded {file_name}: {url}")
68
+ return url
69
  except Exception as e:
70
+ log(f"Upload failed: {e}")
71
  raise
72
 
73
  def notify_render(anime_id: str, episode: int, quality: str, file_url: str, file_name: str, status: int):
 
79
  "file_name": file_name,
80
  "status": status
81
  }
82
+ log(f"Notifying Render status={status} ep={episode} {quality}")
83
  try:
84
  requests.post(RENDER_UPDATE_ENDPOINT, json=payload, timeout=10)
85
  except Exception as e:
86
+ log(f"Notify failed: {e}")
 
 
 
 
 
 
 
 
87
 
88
  def blur_video(input_path: str) -> str:
89
  output = tempfile.mktemp(suffix="_blurred.mp4")
90
  filter_graph = (
91
+ "[0:v]crop=74:17:0:0,boxblur=luma_radius=4:luma_power=1:chroma_radius=0[top];"
92
+ "[0:v][top]overlay=0:0,"
93
+ "drawtext=text='nt-animes':x=8:y=8:fontcolor=white:fontsize=12"
94
  )
95
  cmd = [
96
  "ffmpeg", "-y", "-i", input_path,
97
  "-filter_complex", filter_graph,
98
+ "-c:v", "libx264", "-preset", "veryfast", "-crf", "23",
99
+ "-c:a", "copy", output
 
 
 
 
 
100
  ]
101
  try:
102
  subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
103
  return output
104
  except Exception as e:
105
+ log(f"Blur failed: {e}")
106
  raise
107
 
108
  def process_anime(anime_id: str, anime_name: str):
109
+ log(f"Started processing {anime_id} - {anime_name}")
110
  episode = 1
111
  while True:
112
  episode_processed = False
 
115
  local_file = download_video(anime_id, episode, quality)
116
  if not local_file:
117
  continue
118
+
119
+ log(f"Blurring ep {episode} {quality}")
120
  blurred_file = blur_video(local_file)
121
  os.remove(local_file)
122
+
123
  file_name = get_filename(anime_name, episode, quality)
124
  file_url = upload_to_0x0(blurred_file, file_name)
125
  os.remove(blurred_file)
126
+
127
  notify_render(anime_id, episode, quality, file_url, file_name, 2)
128
  episode_processed = True
129
+
130
+ except Exception:
 
 
 
131
  notify_render(anime_id, episode, quality, "", "", 3)
132
+
133
  if not episode_processed:
134
+ log("No more episodes")
135
+ notify_render(anime_id, 0, "", "", "", 5)
136
  break
137
  episode += 1
138
+ log("Processing complete")
139
 
140
  @app.post("/start")
141
+ def start(payload: StartPayload, bg: BackgroundTasks):
142
+ log(f"Queueing {payload.anime_id} - {payload.anime_name}")
143
  with queue_lock:
144
+ bg.add_task(process_anime, payload.anime_id, payload.anime_name)
145
+ return {"code": 4, "message": "Queued"}