Spaces:
Paused
Paused
File size: 7,680 Bytes
2ab5f89 5efa5ee da44638 5efa5ee f505705 5c6ae28 5efa5ee 2ab5f89 5efa5ee 7f9534f 5efa5ee f0de3f7 5efa5ee f0de3f7 5efa5ee f0de3f7 5efa5ee da44638 5efa5ee da44638 5efa5ee da44638 f0de3f7 5efa5ee da44638 2ab5f89 da44638 2ab5f89 da44638 5efa5ee f0de3f7 5efa5ee da44638 f505705 2ab5f89 7f9534f bb9c4a8 5efa5ee 5c6ae28 f0de3f7 5c6ae28 f505705 5c6ae28 5efa5ee 5c6ae28 5efa5ee 5c6ae28 5efa5ee 5c6ae28 da44638 2ab5f89 da44638 5c6ae28 da44638 2ab5f89 da44638 5efa5ee f0de3f7 5efa5ee 4e15391 f0de3f7 5efa5ee f0de3f7 5efa5ee f0de3f7 f505705 f0de3f7 f505705 7f9534f f505705 5c6ae28 5efa5ee 8c81b5f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
from flask import Flask, jsonify, render_template, request, Response
import os
import json
import re
import urllib.parse
from threading import Thread
import uuid
from video import ffmpeg_stream
from indexer import indexer
from dotenv import load_dotenv
from tvdb import fetch_and_cache_json
load_dotenv()
INDEX_FILE = os.getenv("INDEX_FILE")
TOKEN = os.getenv("TOKEN")
REPO = os.getenv("REPO")
CACHE_DIR = os.getenv("CACHE_DIR")
if not os.path.exists(CACHE_DIR):
os.makedirs(CACHE_DIR)
if not os.path.exists(INDEX_FILE):
raise FileNotFoundError(f"{INDEX_FILE} not found. Please make sure the file exists.")
indexer()
with open(INDEX_FILE, 'r') as f:
file_structure = json.load(f)
def prefetch_metadata():
for item in file_structure:
if 'contents' in item:
for sub_item in item['contents']:
original_title = sub_item['path'].split('/')[-1]
media_type = 'series' if item['path'].startswith('tv') else 'movie'
title = original_title
year = None
match = re.search(r'\((\d{4})\)', original_title)
if match:
year_str = match.group(1)
if year_str.isdigit() and len(year_str) == 4:
title = original_title[:match.start()].strip()
year = int(year_str)
else:
parts = original_title.rsplit(' ', 1)
if len(parts) > 1 and parts[-1].isdigit() and len(parts[-1]) == 4:
title = parts[0].strip()
year = int(parts[-1])
fetch_and_cache_json(original_title, title, media_type, year)
def get_film_file_path(title):
decoded_title = urllib.parse.unquote(title)
normalized_title = decoded_title.split(' (')[0].strip()
for item in file_structure:
if item['path'].startswith('films'):
for sub_item in item['contents']:
sub_item_title = sub_item['path'].split('/')[-1]
normalized_sub_item_title = sub_item_title.split(' (')[0].strip()
if normalized_title == normalized_sub_item_title:
for file in sub_item['contents']:
if file['type'] == 'file':
return file['path']
return None
def get_tv_show_seasons(title):
seasons = []
for item in file_structure:
if item['path'].startswith('tv'):
for sub_item in item['contents']:
if sub_item['type'] == 'directory' and title in sub_item['path']:
for season in sub_item['contents']:
if season['type'] == 'directory':
episodes = []
for episode in season['contents']:
if episode['type'] == 'file':
episodes.append({
"title": episode['path'].split('/')[-1],
"path": episode['path']
})
seasons.append({
"season": season['path'].split('/')[-1],
"episodes": episodes
})
return seasons
return []
def start_prefetching():
prefetch_metadata()
def generate(file_url):
# Generate a unique stream ID
stream_id = str(uuid.uuid4())
output_dir = os.path.join(CACHE_DIR, "stream", stream_id)
# Ensure output directory exists
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Set up HLS streaming
token = TOKEN
_, _ = ffmpeg_stream(file_url, token, output_dir=output_dir, stream_id=stream_id)
return stream_id
thread = Thread(target=start_prefetching)
thread.daemon = True
thread.start()
app = Flask(__name__)
@app.route('/')
def home():
return render_template('index.html')
@app.route('/tvshow_player')
def tvshow_player():
return render_template('player.html')
@app.route('/film_player')
def film_player():
title = request.args.get('title')
if not title:
return "No film title provided", 400
return render_template('film_player.html', title=urllib.parse.unquote(title))
@app.route('/films')
def films():
return render_template('films.html')
@app.route('/api/films')
def list_films():
films = [item for item in file_structure if item['path'].startswith('films')]
return jsonify([sub_item for film in films for sub_item in film['contents']])
@app.route('/tv')
def tv_shows():
return render_template('tvshows.html')
@app.route('/api/tv')
def list_tv():
tv_shows = [item for item in file_structure if item['path'].startswith('tv')]
return jsonify([sub_item for show in tv_shows for sub_item in show['contents']])
@app.route('/api/film/<path:title>')
def film_page(title):
title = urllib.parse.unquote(title)
film_file_path = get_film_file_path(title)
if not film_file_path:
return jsonify({'error': 'Film not found'}), 404
json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.json")
if os.path.exists(json_cache_path):
with open(json_cache_path, 'r') as f:
metadata = json.load(f)
else:
return jsonify({'error': 'Metadata not found'}), 404
return jsonify({
'metadata': metadata,
'file_path': film_file_path
})
@app.route('/api/tv/<path:show_title>')
def tv_page(show_title):
show_title = urllib.parse.unquote(show_title)
seasons = get_tv_show_seasons(show_title)
if not seasons:
return jsonify({'error': 'TV show not found'}), 404
json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(show_title)}.json")
if os.path.exists(json_cache_path):
with open(json_cache_path, 'r') as f:
metadata = json.load(f)
else:
return jsonify({'error': 'Metadata not found'}), 404
return jsonify({
'metadata': metadata,
'seasons': seasons
})
@app.route('/get_metadata')
def get_metadata():
title = request.args.get('title')
if not title:
return jsonify({'error': 'No title provided'}), 400
json_cache_path = os.path.join(CACHE_DIR, f"{urllib.parse.quote(title)}.json")
if os.path.exists(json_cache_path):
with open(json_cache_path, 'r') as f:
data = json.load(f)
return jsonify(data)
return jsonify({'error': 'Metadata not found'}), 404
@app.route('/film/<path:title>')
def film_details(title):
return render_template('film_details_page.html', title=title)
@app.route('/api/stream')
def stream_video():
file_path = request.args.get('path')
if not file_path:
return "File path not provided", 400
file_url = f"https://huggingface.co/{REPO}/resolve/main/{file_path}"
stream_id = generate(file_url)
if stream_id:
# Return the UUID for the client to use
return jsonify({'stream_id': stream_id})
return "Streaming error", 500
@app.route('/stream/<stream_id>')
def stream_file(stream_id):
stream_dir = os.path.join(CACHE_DIR, "stream", stream_id)
playlist_path = os.path.join(stream_dir, 'output.m3u8')
if os.path.exists(playlist_path):
return Response(
open(playlist_path, 'rb').read(),
mimetype='application/vnd.apple.mpegurl'
)
return "Stream not found", 404
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0", port=7860)
|