Document bucket files, improve upload & parsing
Browse filesEnable DB startup and improve bucket handling, seed documentation, and ffmpeg progress parsing.
Changes:
- index.ts: await start_mongo_db() so DB initialization runs.
- lib/bucket.ts: upload_to_bucket now accepts bucket_path and optional REQ0, logs success/failure, notifies caller via REQ0, and uses bucket_path for stored object path.
- sub-router/showtime/helper.ts: stricter skip checks, added FileDownloadInfoOutput import, support document flag, and added document_seed_file to upsert bucket records into Mongo when a bucket file is used.
- sub-router/showtime/v2.ts: pass document: true to find_seed_file, remove stray logs, set fallback=false for proxy requests, unify redirect to proxy_url or original stream, update upload_to_bucket call to include bucket_path and REQ0, and fix progress parsing to handle size units (kB/MB/GB) converting to bytes.
- packages/lib/helpers/client/route.ts: F_is_url now accepts any input type (guards non-string).
These changes ensure uploaded files are stored at correct paths, callers can be notified after upload, bucket-sourced files get recorded in the DB, URL handling is more robust, and ffmpeg progress reporting computes byte sizes correctly.
- src/index.ts +1 -1
- src/lib/bucket.ts +12 -4
- src/sub-router/showtime/helper.ts +57 -11
- src/sub-router/showtime/v2.ts +27 -17
|
@@ -11,7 +11,7 @@ import { NS_runtime } from "../../../../packages/lib/env.runtime";
|
|
| 11 |
import { NS_workers_proxy } from "../../../../packages/lib/proxy-server/workers-proxy";
|
| 12 |
import { start_mongo_db } from "../../../../packages/db/mongo-db/init";
|
| 13 |
|
| 14 |
-
|
| 15 |
|
| 16 |
const { rewriteWorkersUrl, startWorkersProxy, rewriteWorkersUrl_t2, get_dns } =
|
| 17 |
NS_workers_proxy;
|
|
|
|
| 11 |
import { NS_workers_proxy } from "../../../../packages/lib/proxy-server/workers-proxy";
|
| 12 |
import { start_mongo_db } from "../../../../packages/db/mongo-db/init";
|
| 13 |
|
| 14 |
+
await start_mongo_db();
|
| 15 |
|
| 16 |
const { rewriteWorkersUrl, startWorkersProxy, rewriteWorkersUrl_t2, get_dns } =
|
| 17 |
NS_workers_proxy;
|
|
@@ -232,12 +232,14 @@ async function get_latest_hf_bucket_file_by_name(arg0: {
|
|
| 232 |
|
| 233 |
async function upload_to_bucket(arg0: {
|
| 234 |
job_id: string;
|
|
|
|
| 235 |
file_with_path: string;
|
| 236 |
skip?: {
|
| 237 |
probe?: boolean;
|
| 238 |
};
|
|
|
|
| 239 |
}) {
|
| 240 |
-
const { job_id,
|
| 241 |
|
| 242 |
upload_jobs.set(job_id, {
|
| 243 |
status: "in-progress",
|
|
@@ -272,20 +274,26 @@ async function upload_to_bucket(arg0: {
|
|
| 272 |
accessToken: credentials.accessToken,
|
| 273 |
files: [
|
| 274 |
{
|
| 275 |
-
path:
|
| 276 |
content: blob
|
| 277 |
}
|
| 278 |
]
|
| 279 |
})
|
| 280 |
});
|
| 281 |
|
| 282 |
-
console.log("\n", "🔥 UPLOAD BUCKET RESULTS: ", { E__ }, { R__ }, "\n");
|
| 283 |
-
|
| 284 |
upload_jobs.delete(job_id);
|
| 285 |
|
| 286 |
if (E__) {
|
|
|
|
| 287 |
return { success: false };
|
| 288 |
}
|
| 289 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 290 |
return { success: true };
|
| 291 |
}
|
|
|
|
| 232 |
|
| 233 |
async function upload_to_bucket(arg0: {
|
| 234 |
job_id: string;
|
| 235 |
+
bucket_path: string;
|
| 236 |
file_with_path: string;
|
| 237 |
skip?: {
|
| 238 |
probe?: boolean;
|
| 239 |
};
|
| 240 |
+
REQ0?: URL;
|
| 241 |
}) {
|
| 242 |
+
const { job_id, bucket_path, skip, file_with_path, REQ0 } = arg0;
|
| 243 |
|
| 244 |
upload_jobs.set(job_id, {
|
| 245 |
status: "in-progress",
|
|
|
|
| 274 |
accessToken: credentials.accessToken,
|
| 275 |
files: [
|
| 276 |
{
|
| 277 |
+
path: bucket_path,
|
| 278 |
content: blob
|
| 279 |
}
|
| 280 |
]
|
| 281 |
})
|
| 282 |
});
|
| 283 |
|
|
|
|
|
|
|
| 284 |
upload_jobs.delete(job_id);
|
| 285 |
|
| 286 |
if (E__) {
|
| 287 |
+
console.log("\n", "❌ UPLOAD BUCKET FAILED", E__, "\n");
|
| 288 |
return { success: false };
|
| 289 |
}
|
| 290 |
|
| 291 |
+
console.log("\n", "🔥 UPLOAD BUCKET DONE", "\n");
|
| 292 |
+
|
| 293 |
+
if (REQ0) {
|
| 294 |
+
REQ0.searchParams.set("ops", "just_check");
|
| 295 |
+
fetch(REQ0.toString());
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
return { success: true };
|
| 299 |
}
|
|
@@ -5,6 +5,7 @@ import { NS_bucket } from "../../lib/bucket";
|
|
| 5 |
import { NS_promise } from "../../lib/promise";
|
| 6 |
import node_fs from "node:fs";
|
| 7 |
import { NS_ffmpeg_v2 } from "../../lib/ffmpeg-v2";
|
|
|
|
| 8 |
|
| 9 |
export const NS_showtime_v2_helper = {
|
| 10 |
find_seed_file
|
|
@@ -28,6 +29,7 @@ async function find_seed_file(arg0: {
|
|
| 28 |
db?: boolean;
|
| 29 |
bucket?: boolean;
|
| 30 |
};
|
|
|
|
| 31 |
}) {
|
| 32 |
const {
|
| 33 |
sbe_id,
|
|
@@ -37,7 +39,8 @@ async function find_seed_file(arg0: {
|
|
| 37 |
job_id,
|
| 38 |
S3Dir,
|
| 39 |
cleanup_corruption,
|
| 40 |
-
skip
|
|
|
|
| 41 |
} = arg0;
|
| 42 |
|
| 43 |
let { picture_quality } = arg0;
|
|
@@ -49,7 +52,7 @@ async function find_seed_file(arg0: {
|
|
| 49 |
// check database first
|
| 50 |
const [_, db_file_info] = await NS_promise.F_catch_promise({
|
| 51 |
promise: (async () => {
|
| 52 |
-
if (skip?.db) return;
|
| 53 |
|
| 54 |
const _ =
|
| 55 |
await NS_mongo_db_record_factory.NS_record_factory_s3_bucket.findRecordsByFingerprint(
|
|
@@ -67,10 +70,10 @@ async function find_seed_file(arg0: {
|
|
| 67 |
})()
|
| 68 |
});
|
| 69 |
|
| 70 |
-
const in_db =
|
| 71 |
|
| 72 |
if (in_db) {
|
| 73 |
-
const stream_link = db_file_info.url;
|
| 74 |
|
| 75 |
const _u = new URL(stream_link);
|
| 76 |
_u.searchParams.set("download", "true");
|
|
@@ -85,7 +88,7 @@ async function find_seed_file(arg0: {
|
|
| 85 |
// check bucket
|
| 86 |
const [__, bucket_file_info] = await NS_promise.F_catch_promise({
|
| 87 |
promise: (async () => {
|
| 88 |
-
if (skip?.bucket) return;
|
| 89 |
|
| 90 |
return NS_bucket.get_latest_hf_bucket_file_by_name({
|
| 91 |
folder_path: cache_folder,
|
|
@@ -95,16 +98,26 @@ async function find_seed_file(arg0: {
|
|
| 95 |
})()
|
| 96 |
});
|
| 97 |
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
const in_bucket =
|
| 101 |
-
bucket_file_info?.url && NS_routes_c.F_is_url(bucket_file_info.url);
|
| 102 |
|
| 103 |
if (in_bucket) {
|
| 104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
}
|
| 106 |
|
| 107 |
-
if (skip?.local) return;
|
| 108 |
|
| 109 |
// check local
|
| 110 |
const file =
|
|
@@ -224,3 +237,36 @@ async function find_seed_file(arg0: {
|
|
| 224 |
async function find_seed_local_file(arg0: {}) {
|
| 225 |
const {} = arg0;
|
| 226 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
import { NS_promise } from "../../lib/promise";
|
| 6 |
import node_fs from "node:fs";
|
| 7 |
import { NS_ffmpeg_v2 } from "../../lib/ffmpeg-v2";
|
| 8 |
+
import { FileDownloadInfoOutput } from "@huggingface/hub";
|
| 9 |
|
| 10 |
export const NS_showtime_v2_helper = {
|
| 11 |
find_seed_file
|
|
|
|
| 29 |
db?: boolean;
|
| 30 |
bucket?: boolean;
|
| 31 |
};
|
| 32 |
+
document?: boolean;
|
| 33 |
}) {
|
| 34 |
const {
|
| 35 |
sbe_id,
|
|
|
|
| 39 |
job_id,
|
| 40 |
S3Dir,
|
| 41 |
cleanup_corruption,
|
| 42 |
+
skip,
|
| 43 |
+
document
|
| 44 |
} = arg0;
|
| 45 |
|
| 46 |
let { picture_quality } = arg0;
|
|
|
|
| 52 |
// check database first
|
| 53 |
const [_, db_file_info] = await NS_promise.F_catch_promise({
|
| 54 |
promise: (async () => {
|
| 55 |
+
if (skip?.db === true) return;
|
| 56 |
|
| 57 |
const _ =
|
| 58 |
await NS_mongo_db_record_factory.NS_record_factory_s3_bucket.findRecordsByFingerprint(
|
|
|
|
| 70 |
})()
|
| 71 |
});
|
| 72 |
|
| 73 |
+
const in_db = NS_routes_c.F_is_url(db_file_info?.url);
|
| 74 |
|
| 75 |
if (in_db) {
|
| 76 |
+
const stream_link = db_file_info!.url;
|
| 77 |
|
| 78 |
const _u = new URL(stream_link);
|
| 79 |
_u.searchParams.set("download", "true");
|
|
|
|
| 88 |
// check bucket
|
| 89 |
const [__, bucket_file_info] = await NS_promise.F_catch_promise({
|
| 90 |
promise: (async () => {
|
| 91 |
+
if (skip?.bucket === true) return;
|
| 92 |
|
| 93 |
return NS_bucket.get_latest_hf_bucket_file_by_name({
|
| 94 |
folder_path: cache_folder,
|
|
|
|
| 98 |
})()
|
| 99 |
});
|
| 100 |
|
| 101 |
+
const in_bucket = NS_routes_c.F_is_url(bucket_file_info?.url);
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
if (in_bucket) {
|
| 104 |
+
const stream_link = bucket_file_info!.url;
|
| 105 |
+
|
| 106 |
+
if (!in_db && skip?.db !== true && document === true) {
|
| 107 |
+
document_seed_file({
|
| 108 |
+
job_id,
|
| 109 |
+
sbe_id,
|
| 110 |
+
file_id,
|
| 111 |
+
stream_link,
|
| 112 |
+
name: output_destination.og,
|
| 113 |
+
file_info: bucket_file_info!
|
| 114 |
+
});
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
return stream_link;
|
| 118 |
}
|
| 119 |
|
| 120 |
+
if (skip?.local === true) return;
|
| 121 |
|
| 122 |
// check local
|
| 123 |
const file =
|
|
|
|
| 237 |
async function find_seed_local_file(arg0: {}) {
|
| 238 |
const {} = arg0;
|
| 239 |
}
|
| 240 |
+
|
| 241 |
+
async function document_seed_file(arg0: {
|
| 242 |
+
job_id: string;
|
| 243 |
+
sbe_id: string;
|
| 244 |
+
file_id: string;
|
| 245 |
+
stream_link: string;
|
| 246 |
+
file_info: FileDownloadInfoOutput;
|
| 247 |
+
name: string;
|
| 248 |
+
}) {
|
| 249 |
+
const { job_id, sbe_id, file_id, stream_link, file_info, name } = arg0;
|
| 250 |
+
|
| 251 |
+
const [E_, R_] = await NS_promise.F_catch_promise({
|
| 252 |
+
promise:
|
| 253 |
+
NS_mongo_db_record_factory.NS_record_factory_s3_bucket.upsertRecord(
|
| 254 |
+
{ job_id, sbe_id, file_id },
|
| 255 |
+
{
|
| 256 |
+
provider: "hugging face",
|
| 257 |
+
job_id,
|
| 258 |
+
sbe_id,
|
| 259 |
+
file_id,
|
| 260 |
+
stream_link,
|
| 261 |
+
file_info,
|
| 262 |
+
name
|
| 263 |
+
}
|
| 264 |
+
)
|
| 265 |
+
});
|
| 266 |
+
|
| 267 |
+
if (E_) {
|
| 268 |
+
return E_;
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
return R_;
|
| 272 |
+
}
|
|
@@ -116,8 +116,6 @@ const sub_router = new Elysia({ prefix: "/showtimeV2" }).get(
|
|
| 116 |
|
| 117 |
const filePath = path.join(S3Dir, file_id);
|
| 118 |
|
| 119 |
-
// console.log("\n", "FILE PATH:", filePath, "\n");
|
| 120 |
-
|
| 121 |
return filePath;
|
| 122 |
} catch (e) {}
|
| 123 |
})();
|
|
@@ -254,7 +252,8 @@ const sub_router = new Elysia({ prefix: "/showtimeV2" }).get(
|
|
| 254 |
file_id: clean_file_id,
|
| 255 |
job_id,
|
| 256 |
S3Dir,
|
| 257 |
-
cleanup_corruption: true
|
|
|
|
| 258 |
})
|
| 259 |
});
|
| 260 |
|
|
@@ -307,17 +306,16 @@ const sub_router = new Elysia({ prefix: "/showtimeV2" }).get(
|
|
| 307 |
use_h_version: true
|
| 308 |
},
|
| 309 |
env: "cloudflare",
|
| 310 |
-
fallback:
|
| 311 |
}
|
| 312 |
})
|
| 313 |
.json()
|
| 314 |
});
|
| 315 |
|
| 316 |
-
const
|
|
|
|
| 317 |
|
| 318 |
-
|
| 319 |
-
return ctx.redirect(data?.proxy_url, 301);
|
| 320 |
-
}
|
| 321 |
} else {
|
| 322 |
// if seed is file set headers
|
| 323 |
construct_response_headers({
|
|
@@ -463,9 +461,7 @@ const sub_router = new Elysia({ prefix: "/showtimeV2" }).get(
|
|
| 463 |
});
|
| 464 |
|
| 465 |
if (progress_data && Object.entries(progress_data).length) {
|
| 466 |
-
|
| 467 |
-
// (parseFloat(`${seek_size_bytes}`) || 0) +
|
| 468 |
-
// (parseFloat(`${progress_data.size_bytes}`) || 0);
|
| 469 |
|
| 470 |
if (APP_ENV === "dev") console.log(progress_data, "\n");
|
| 471 |
|
|
@@ -523,7 +519,12 @@ const sub_router = new Elysia({ prefix: "/showtimeV2" }).get(
|
|
| 523 |
});
|
| 524 |
|
| 525 |
if (delivery_mode === "download" && file_with_path) {
|
| 526 |
-
NS_bucket.upload_to_bucket({
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 527 |
}
|
| 528 |
}
|
| 529 |
} else {
|
|
@@ -644,17 +645,26 @@ function F_stderr_parse_progress(arg0: {
|
|
| 644 |
const progress: Record<string, any> = {};
|
| 645 |
|
| 646 |
const fps = stderr_line.match(/fps=\s*(\d+)/);
|
| 647 |
-
const size = stderr_line.match(/size=\s*(\d+)/);
|
| 648 |
const time = stderr_line.match(/time=(\d{2}:\d{2}:\d{2}\.\d{2})/);
|
| 649 |
const speed = stderr_line.match(/speed=\s*([\d.]+x)/);
|
| 650 |
const bitrate = stderr_line.match(/bitrate=\s*([\d.]+kbits\/s)/);
|
| 651 |
|
| 652 |
-
if (!seek_size_bytes) {
|
| 653 |
-
seek_size_bytes = size ? parseFloat(`${size[1]}`) : 0;
|
| 654 |
-
}
|
| 655 |
-
|
| 656 |
if (fps) progress.fps = parseInt(fps[1]);
|
| 657 |
if (size) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 658 |
progress.size_bytes = seek_size_bytes;
|
| 659 |
progress.size = NS_ffmpeg.F_format_size(seek_size_bytes);
|
| 660 |
}
|
|
|
|
| 116 |
|
| 117 |
const filePath = path.join(S3Dir, file_id);
|
| 118 |
|
|
|
|
|
|
|
| 119 |
return filePath;
|
| 120 |
} catch (e) {}
|
| 121 |
})();
|
|
|
|
| 252 |
file_id: clean_file_id,
|
| 253 |
job_id,
|
| 254 |
S3Dir,
|
| 255 |
+
cleanup_corruption: true,
|
| 256 |
+
document: true
|
| 257 |
})
|
| 258 |
});
|
| 259 |
|
|
|
|
| 306 |
use_h_version: true
|
| 307 |
},
|
| 308 |
env: "cloudflare",
|
| 309 |
+
fallback: false
|
| 310 |
}
|
| 311 |
})
|
| 312 |
.json()
|
| 313 |
});
|
| 314 |
|
| 315 |
+
const new_stream_link =
|
| 316 |
+
(R_ as any)?.proxy_url || stream_link.toString();
|
| 317 |
|
| 318 |
+
return ctx.redirect(new_stream_link, 301);
|
|
|
|
|
|
|
| 319 |
} else {
|
| 320 |
// if seed is file set headers
|
| 321 |
construct_response_headers({
|
|
|
|
| 461 |
});
|
| 462 |
|
| 463 |
if (progress_data && Object.entries(progress_data).length) {
|
| 464 |
+
seek_size_bytes = parseFloat(`${progress_data.size_bytes}`) || 0;
|
|
|
|
|
|
|
| 465 |
|
| 466 |
if (APP_ENV === "dev") console.log(progress_data, "\n");
|
| 467 |
|
|
|
|
| 519 |
});
|
| 520 |
|
| 521 |
if (delivery_mode === "download" && file_with_path) {
|
| 522 |
+
NS_bucket.upload_to_bucket({
|
| 523 |
+
job_id,
|
| 524 |
+
bucket_path: `${cache_folder}/${file_id}`,
|
| 525 |
+
file_with_path,
|
| 526 |
+
REQ0
|
| 527 |
+
});
|
| 528 |
}
|
| 529 |
}
|
| 530 |
} else {
|
|
|
|
| 645 |
const progress: Record<string, any> = {};
|
| 646 |
|
| 647 |
const fps = stderr_line.match(/fps=\s*(\d+)/);
|
| 648 |
+
const size = stderr_line.match(/size=\s*([\d.]+)([kMGT]?B)/);
|
| 649 |
const time = stderr_line.match(/time=(\d{2}:\d{2}:\d{2}\.\d{2})/);
|
| 650 |
const speed = stderr_line.match(/speed=\s*([\d.]+x)/);
|
| 651 |
const bitrate = stderr_line.match(/bitrate=\s*([\d.]+kbits\/s)/);
|
| 652 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 653 |
if (fps) progress.fps = parseInt(fps[1]);
|
| 654 |
if (size) {
|
| 655 |
+
const value = parseFloat(size[1]);
|
| 656 |
+
const unit = size[2] || "B";
|
| 657 |
+
|
| 658 |
+
const multipliers: Record<string, number> = {
|
| 659 |
+
B: 1,
|
| 660 |
+
kB: 1024,
|
| 661 |
+
MB: 1024 ** 2,
|
| 662 |
+
GB: 1024 ** 3,
|
| 663 |
+
TB: 1024 ** 4
|
| 664 |
+
};
|
| 665 |
+
|
| 666 |
+
const seek_size_bytes = Math.round(value * (multipliers[unit] || 1));
|
| 667 |
+
|
| 668 |
progress.size_bytes = seek_size_bytes;
|
| 669 |
progress.size = NS_ffmpeg.F_format_size(seek_size_bytes);
|
| 670 |
}
|