File size: 6,168 Bytes
c0942b9
 
 
 
 
3dc3878
 
 
 
 
 
 
 
 
 
 
 
 
 
c0942b9
3dc3878
 
 
 
 
 
 
 
c0942b9
3dc3878
 
 
 
 
 
 
 
 
 
 
 
c0942b9
 
 
 
 
3dc3878
 
 
 
 
 
 
c0942b9
3dc3878
 
 
 
c0942b9
3dc3878
 
c0942b9
 
3dc3878
c0942b9
 
3dc3878
c0942b9
3dc3878
 
 
 
 
 
 
 
 
 
c0942b9
3dc3878
 
 
 
 
 
 
 
 
 
 
 
 
c0942b9
3dc3878
 
c0942b9
3dc3878
 
c0942b9
3dc3878
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c0942b9
 
 
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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Downloadwella to Hugging Face Frame Extractor</title>
    <style>
        body { font-family: sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
        .container { max-width: 800px; margin: auto; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h1 { color: #0056b3; }
        form { margin-top: 20px; display: flex; flex-direction: column; gap: 10px; }
        input[type="text"] { padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; }
        button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
        button:hover { background-color: #0056b3; }
        .status-box { background-color: #e9ecef; border: 1px solid #ced4da; padding: 15px; border-radius: 4px; margin-top: 20px; }
        .log-entry { margin-bottom: 5px; border-bottom: 1px dotted #ccc; padding-bottom: 3px; }
        .error { color: red; font-weight: bold; }
        .success { color: green; font-weight: bold; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Downloadwella to Hugging Face Frame Extractor</h1>
        <p>Enter a Downloadwella URL to download the video, extract frames, and upload them as a zip to Hugging Face.</p>

        <form id="processForm">
            <input type="text" id="videoUrl" name="video_url" placeholder="Enter Downloadwella URL (e.g., https://downloadwella.com/some-video-id)" required>
            <button type="submit">Start Processing</button>
        </form>

        <div class="status-box">
            <h2>Processing Status</h2>
            <p><strong>Is Running:</strong> <span id="isRunning">{{ status.is_running }}</span></p>
            <p><strong>Current Action:</strong> <span id="currentAction">{{ status.current_action }}</span></p>
            <p><strong>Last Processed URL:</strong> <span id="lastProcessedUrl">{{ status.last_processed_url if status.last_processed_url else 'N/A' }}</span></p>
            <p><strong>Processed Count:</strong> <span id="processedCount">{{ status.processed_count }}</span></p>
            <h3>Logs:</h3>
            <div id="logs" style="max-height: 300px; overflow-y: scroll; background-color: #fff; padding: 10px; border-radius: 4px;">
                {% for log in status.logs %}
                    <div class="log-entry">{{ log }}</div>
                {% endfor %}
            </div>
        </div>
    </div>

    <script>
        const processForm = document.getElementById('processForm');
        const videoUrlInput = document.getElementById('videoUrl');
        const isRunningSpan = document.getElementById('isRunning');
        const currentActionSpan = document.getElementById('currentAction');
        const lastProcessedUrlSpan = document.getElementById('lastProcessedUrl');
        const processedCountSpan = document.getElementById('processedCount');
        const logsDiv = document.getElementById('logs');

        processForm.addEventListener('submit', async (event) => {
            event.preventDefault();
            const videoUrl = videoUrlInput.value;
            if (!videoUrl) return;

            logsDiv.innerHTML = ''; // Clear previous logs
            addLog('Initiating processing...');

            try {
                const response = await fetch('/start', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: `video_url=${encodeURIComponent(videoUrl)}`
                });
                const data = await response.json();
                addLog(data.message);
                if (data.message === "Processor started") {
                    // Start polling for status updates
                    pollStatus();
                }
            } catch (error) {
                addLog(`Error starting process: ${error}`, true);
            }
        });

        async function fetchStatus() {
            try {
                const response = await fetch('/stats');
                const status = await response.json();
                isRunningSpan.textContent = status.is_running;
                currentActionSpan.textContent = status.current_action;
                lastProcessedUrlSpan.textContent = status.last_processed_url || 'N/A';
                processedCountSpan.textContent = status.processed_count;
                
                // Only update logs if there are new entries or status changed
                if (status.logs.length !== logsDiv.children.length) {
                    logsDiv.innerHTML = '';
                    status.logs.forEach(log => addLog(log));
                }

                return status.is_running;
            } catch (error) {
                addLog(`Error fetching status: ${error}`, true);
                return false;
            }
        }

        function addLog(message, isError = false) {
            const logEntry = document.createElement('div');
            logEntry.classList.add('log-entry');
            if (isError) {
                logEntry.classList.add('error');
            }
            logEntry.textContent = message;
            logsDiv.appendChild(logEntry);
            logsDiv.scrollTop = logsDiv.scrollHeight; // Auto-scroll to bottom
        }

        let pollingInterval;
        function pollStatus() {
            if (pollingInterval) clearInterval(pollingInterval);
            pollingInterval = setInterval(async () => {
                const running = await fetchStatus();
                if (!running && currentActionSpan.textContent !== "Idle" && currentActionSpan.textContent !== "Error") {
                    addLog("Processing finished or stopped.");
                    clearInterval(pollingInterval);
                }
            }, 3000); // Poll every 3 seconds
        }

        // Initial status fetch on page load
        fetchStatus();
        pollStatus(); // Start polling immediately

    </script>
</body>
</html>