|
1 | 1 | (function () { |
2 | 2 | "use strict"; |
3 | 3 |
|
4 | | - let STASHMARKER_API_URL = "https://cc1234-stashtag.hf.space/api/predict"; |
| 4 | + let STASHMARKER_API_BASE = "https://cc1234-stashtag-onnx.hf.space"; |
5 | 5 |
|
6 | 6 | var OPTIONS = [ |
7 | 7 | "Anal", |
|
2241 | 2241 | const [, scene_id] = getScenarioAndID(); |
2242 | 2242 | let time; |
2243 | 2243 | let tagId; |
2244 | | - const tagLower = frame.tag.label.toLowerCase(); |
| 2244 | + const tagLower = frame.tag.label.toLowerCase().replace(/_/g, " "); |
2245 | 2245 |
|
2246 | 2246 | if (tags[tagLower] === undefined) { |
2247 | 2247 | const tagID = await createTag(tagLower); |
|
2543 | 2543 | }); |
2544 | 2544 | } |
2545 | 2545 |
|
| 2546 | + async function gradioCall(fn_index, image, vtt, threshold, retries = 3) { |
| 2547 | + for (let attempt = 0; attempt < retries; attempt++) { |
| 2548 | + try { |
| 2549 | + return await _gradioCall(fn_index, image, vtt, threshold); |
| 2550 | + } catch (err) { |
| 2551 | + if (attempt === retries - 1) throw err; |
| 2552 | + await new Promise((r) => setTimeout(r, 3000)); |
| 2553 | + } |
| 2554 | + } |
| 2555 | + } |
| 2556 | + |
| 2557 | + async function _gradioCall(fn_index, image, vtt, threshold) { |
| 2558 | + const session_hash = crypto.randomUUID |
| 2559 | + ? crypto.randomUUID() |
| 2560 | + : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { |
| 2561 | + const r = (Math.random() * 16) | 0; |
| 2562 | + return (c === "x" ? r : (r & 0x3) | 0x8).toString(16); |
| 2563 | + }); |
| 2564 | + |
| 2565 | + const queueResponse = await fetch(STASHMARKER_API_BASE + "/gradio_api/queue/join", { |
| 2566 | + method: "POST", |
| 2567 | + headers: { "Content-Type": "application/json" }, |
| 2568 | + body: JSON.stringify({ |
| 2569 | + data: [ |
| 2570 | + { url: image, meta: { _type: "gradio.FileData" }, orig_name: "sprite.jpg" }, |
| 2571 | + vtt, |
| 2572 | + threshold, |
| 2573 | + ], |
| 2574 | + fn_index: fn_index, |
| 2575 | + session_hash: session_hash, |
| 2576 | + }), |
| 2577 | + }); |
| 2578 | + |
| 2579 | + if (!queueResponse.ok) { |
| 2580 | + throw new Error("HTTP " + queueResponse.status); |
| 2581 | + } |
| 2582 | + |
| 2583 | + const sseUrl = STASHMARKER_API_BASE + "/gradio_api/queue/data?session_hash=" + session_hash; |
| 2584 | + |
| 2585 | + const controller = new AbortController(); |
| 2586 | + const timeout = setTimeout(() => controller.abort(), 120000); |
| 2587 | + |
| 2588 | + let text; |
| 2589 | + try { |
| 2590 | + const resp = await fetch(sseUrl, { signal: controller.signal }); |
| 2591 | + if (!resp.ok) { |
| 2592 | + throw new Error("HTTP " + resp.status); |
| 2593 | + } |
| 2594 | + text = await resp.text(); |
| 2595 | + } finally { |
| 2596 | + clearTimeout(timeout); |
| 2597 | + } |
| 2598 | + |
| 2599 | + let result; |
| 2600 | + for (const line of text.split("\n")) { |
| 2601 | + if (line.startsWith("data: ")) { |
| 2602 | + try { |
| 2603 | + const msg = JSON.parse(line.slice(6)); |
| 2604 | + if (msg.msg === "process_completed") { |
| 2605 | + if (msg.success === false) { |
| 2606 | + throw new Error(msg.output?.error || "Model inference failed"); |
| 2607 | + } |
| 2608 | + result = [msg.output?.data?.[0]]; |
| 2609 | + break; |
| 2610 | + } |
| 2611 | + if (msg.msg === "error") { |
| 2612 | + throw new Error(msg.output?.error || "API error"); |
| 2613 | + } |
| 2614 | + } catch (e) { |
| 2615 | + if ( |
| 2616 | + e.message === "Model inference failed" || |
| 2617 | + e.message === "API error" |
| 2618 | + ) |
| 2619 | + throw e; |
| 2620 | + } |
| 2621 | + } |
| 2622 | + } |
| 2623 | + |
| 2624 | + if (result === undefined) throw new Error("No result received"); |
| 2625 | + return result; |
| 2626 | + } |
| 2627 | + |
2546 | 2628 | function instance$3($$self, $$props, $$invalidate) { |
2547 | 2629 | let { $$slots: slots = {}, $$scope } = $$props; |
2548 | 2630 | validate_slots("MarkerButton", slots, []); |
|
2569 | 2651 |
|
2570 | 2652 | let vtt = await download(vtt_url); |
2571 | 2653 |
|
2572 | | - // query the api with a threshold of 0.4 as we want to do the filtering ourselves |
2573 | | - var data = { data: [image, vtt, 0.4] }; |
2574 | | - |
2575 | | - fetch(STASHMARKER_API_URL + "_1", { |
2576 | | - method: "POST", |
2577 | | - headers: { |
2578 | | - "Content-Type": "application/json; charset=utf-8", |
2579 | | - }, |
2580 | | - body: JSON.stringify(data), |
2581 | | - }) |
2582 | | - .then((response) => { |
2583 | | - if (response.status !== 200) { |
2584 | | - $$invalidate(0, (scanner = false)); |
2585 | | - alert( |
2586 | | - "Something went wrong. It's likely a server issue, Please try again later." |
2587 | | - ); |
2588 | | - return; |
2589 | | - } |
2590 | | - |
2591 | | - return response.json(); |
2592 | | - }) |
2593 | | - .then((data) => { |
2594 | | - $$invalidate(0, (scanner = false)); |
2595 | | - let frames = data.data[0]; |
2596 | | - $$invalidate(0, (scanner = false)); |
2597 | | - |
2598 | | - if (frames.length === 0) { |
2599 | | - alert("No tags found"); |
2600 | | - return; |
2601 | | - } |
| 2654 | + try { |
| 2655 | + let result = await gradioCall(1, image, vtt, 0.4); |
| 2656 | + let frames = result[0]; |
2602 | 2657 |
|
2603 | | - // find a div with class row |
2604 | | - let row = document.querySelector(".row"); |
| 2658 | + $$invalidate(0, (scanner = false)); |
2605 | 2659 |
|
2606 | | - new MarkerMatches({ target: row, props: { frames, url } }); |
2607 | | - }) |
2608 | | - .catch((error) => { |
2609 | | - $$invalidate(0, (scanner = false)); |
| 2660 | + if (!frames || frames.length === 0) { |
| 2661 | + alert("No tags found"); |
| 2662 | + return; |
| 2663 | + } |
2610 | 2664 |
|
2611 | | - if (error.message === "") { |
2612 | | - alert("Error: Service may be down. please try again later."); |
2613 | | - } else { |
2614 | | - alert("Error: " + error.message); |
2615 | | - } |
2616 | | - }); |
| 2665 | + let row = document.querySelector(".row"); |
| 2666 | + new MarkerMatches({ target: row, props: { frames, url } }); |
| 2667 | + } catch (error) { |
| 2668 | + $$invalidate(0, (scanner = false)); |
| 2669 | + alert("Error: " + (error.message || "Service may be down. Please try again later.")); |
| 2670 | + } |
2617 | 2671 | } |
2618 | 2672 |
|
2619 | 2673 | const writable_props = []; |
|
2630 | 2684 | $$self.$capture_state = () => ({ |
2631 | 2685 | getScenarioAndID, |
2632 | 2686 | getUrlSprite, |
2633 | | - STASHMARKER_API_URL, |
| 2687 | + STASHMARKER_API_BASE, |
2634 | 2688 | MarkerMatches, |
2635 | 2689 | scanner, |
2636 | 2690 | download, |
|
3725 | 3779 | let existingTags = await getTagsForScene(scene_id); |
3726 | 3780 |
|
3727 | 3781 | for (const [tag] of filteredMatches) { |
3728 | | - let tagLower = tag.toLowerCase(); |
| 3782 | + const tagNormalized = tag.replace(/_/g, " "); |
| 3783 | + let tagLower = tagNormalized.toLowerCase(); |
3729 | 3784 |
|
3730 | 3785 | // if tag doesn't exist, create it |
3731 | 3786 | if (tags[tagLower] === undefined) { |
3732 | | - existingTags.push(await createTag(tag)); |
| 3787 | + existingTags.push(await createTag(tagNormalized)); |
3733 | 3788 | } else if (!existingTags.includes(tags[tagLower])) { |
3734 | 3789 | existingTags.push(tags[tagLower]); |
3735 | 3790 | } |
|
4027 | 4082 | reader.readAsDataURL(vblob); |
4028 | 4083 | }); |
4029 | 4084 |
|
4030 | | - // query the api with a threshold of 0.2 as we want to do the filtering ourselves |
4031 | | - var data = { data: [image, vtt, 0.2] }; |
4032 | | - |
4033 | | - fetch(STASHMARKER_API_URL, { |
4034 | | - method: "POST", |
4035 | | - headers: { |
4036 | | - "Content-Type": "application/json; charset=utf-8", |
4037 | | - }, |
4038 | | - body: JSON.stringify(data), |
4039 | | - }) |
4040 | | - .then((response) => { |
4041 | | - if (response.status !== 200) { |
4042 | | - $$invalidate(0, (scanner = false)); |
4043 | | - alert( |
4044 | | - "Something went wrong. It's likely a server issue, Please try again later." |
4045 | | - ); |
4046 | | - return; |
4047 | | - } |
4048 | | - |
4049 | | - return response.json(); |
4050 | | - }) |
4051 | | - .then((data) => { |
4052 | | - $$invalidate(0, (scanner = false)); |
| 4085 | + try { |
| 4086 | + let result = await gradioCall(0, image, vtt, 0.2); |
| 4087 | + let tags = {}; |
| 4088 | + result.forEach((item) => Object.assign(tags, item)); |
4053 | 4089 |
|
4054 | | - if (data.data[0].length === 0) { |
4055 | | - alert("No tags found"); |
4056 | | - return; |
4057 | | - } |
| 4090 | + $$invalidate(0, (scanner = false)); |
4058 | 4091 |
|
4059 | | - // grab stash-tag-threshold from local storage or set to default |
4060 | | - let threshold = localStorage.getItem("stash-tag-threshold") || 0.4; |
| 4092 | + if (Object.keys(tags).length === 0) { |
| 4093 | + alert("No tags found"); |
| 4094 | + return; |
| 4095 | + } |
4061 | 4096 |
|
4062 | | - new TagMatches({ |
4063 | | - target: document.body, |
4064 | | - props: { matches: data.data[0], url, threshold }, |
4065 | | - }); |
4066 | | - }) |
4067 | | - .catch((error) => { |
4068 | | - $$invalidate(0, (scanner = false)); |
| 4097 | + let threshold = localStorage.getItem("stash-tag-threshold") || 0.4; |
4069 | 4098 |
|
4070 | | - if (error.message === "") { |
4071 | | - alert("Error: Service may be down. please try again later."); |
4072 | | - } else { |
4073 | | - alert("Error: " + error.message); |
4074 | | - } |
| 4099 | + new TagMatches({ |
| 4100 | + target: document.body, |
| 4101 | + props: { matches: tags, url, threshold }, |
4075 | 4102 | }); |
| 4103 | + } catch (error) { |
| 4104 | + $$invalidate(0, (scanner = false)); |
| 4105 | + alert("Error: " + (error.message || "Service may be down. Please try again later.")); |
| 4106 | + } |
4076 | 4107 | } |
4077 | 4108 |
|
4078 | 4109 | const writable_props = []; |
|
4089 | 4120 | $$self.$capture_state = () => ({ |
4090 | 4121 | getScenarioAndID, |
4091 | 4122 | getUrlSprite, |
4092 | | - STASHMARKER_API_URL, |
| 4123 | + STASHMARKER_API_BASE, |
4093 | 4124 | TagMatches, |
4094 | 4125 | scanner, |
4095 | 4126 | getTags, |
|
0 commit comments