feat: ingestion status endpoint + pipeline doc with 入库 steps

This commit is contained in:
Accusys
2026-05-17 21:36:55 +08:00
parent 3164a65554
commit d6c8930f84
19 changed files with 4191 additions and 72 deletions

View File

@@ -0,0 +1,180 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>11 Error Codes - Momentry API Docs</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 40px; }
.container { max-width: 960px; margin: 0 auto; background: white; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); padding: 40px; }
h1 { font-size: 24px; margin: 24px 0 12px; }
h2 { font-size: 20px; margin: 20px 0 10px; color: #222; }
h3 { font-size: 16px; margin: 16px 0 8px; color: #444; }
p { line-height: 1.6; margin: 8px 0; }
table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 14px; }
th, td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; }
th { background: #f0f0f0; font-weight: 600; }
code { background: #f0f0f0; padding: 2px 6px; border-radius: 3px; font-size: 13px; }
pre { background: #f8f8f8; border: 1px solid #ddd; border-radius: 6px; padding: 12px; overflow-x: auto; margin: 12px 0; }
pre code { background: none; padding: 0; }
a { color: #0066cc; }
.back { display: inline-block; margin-bottom: 20px; color: #666; }
.back:hover { color: #333; }
</style>
</head>
<body>
<div class="container">
<a class="back" href="index.html">&larr; Back to index</a>
<!-- module: error_codes -->
<!-- description: Standard API error codes -->
<!-- depends: -->
<h2>Error Response Format</h2>
<p>All API errors follow this JSON structure:</p>
<div class="codehilite"><pre><span></span><code><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;success&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;error&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;code&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;E001_NOT_FOUND&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;message&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Resource not found&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;details&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nt">&quot;resource&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;file_uuid&quot;</span><span class="p">,</span><span class="w"> </span><span class="nt">&quot;value&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;abc&quot;</span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<h2>Error Code List</h2>
<h3>Generic Errors (E0xx)</h3>
<table class="table">
<thead>
<tr>
<th>Code</th>
<th>HTTP</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>E001_NOT_FOUND</code></td>
<td>404</td>
<td>Resource not found (file, identity, chunk)</td>
</tr>
<tr>
<td><code>E002_DUPLICATE</code></td>
<td>409</td>
<td>Resource already exists</td>
</tr>
<tr>
<td><code>E003_VALIDATION</code></td>
<td>400</td>
<td>Request parameter validation failed</td>
</tr>
<tr>
<td><code>E004_UNAUTHORIZED</code></td>
<td>401</td>
<td>Invalid API key or token</td>
</tr>
<tr>
<td><code>E005_INTERNAL</code></td>
<td>500</td>
<td>Internal server error</td>
</tr>
</tbody>
</table>
<h3>Processor Errors (E1xx)</h3>
<table class="table">
<thead>
<tr>
<th>Code</th>
<th>HTTP</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>E101_PROCESSOR_FAIL</code></td>
<td>500</td>
<td>Python script execution failed</td>
</tr>
<tr>
<td><code>E102_TIMEOUT</code></td>
<td>504</td>
<td>Processing timeout</td>
</tr>
<tr>
<td><code>E103_RESUME_FAIL</code></td>
<td>500</td>
<td>Resume failed (checkpoint not found)</td>
</tr>
<tr>
<td><code>E104_NO_VIDEO</code></td>
<td>400</td>
<td>Video file path not found</td>
</tr>
</tbody>
</table>
<h3>Identity Errors (E2xx)</h3>
<table class="table">
<thead>
<tr>
<th>Code</th>
<th>HTTP</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>E201_FACE_NOT_FOUND</code></td>
<td>404</td>
<td>Face detection not found</td>
</tr>
<tr>
<td><code>E202_MERGE_CONFLICT</code></td>
<td>409</td>
<td>Identity merge conflict</td>
</tr>
<tr>
<td><code>E203_CANDIDATE_EMPTY</code></td>
<td>404</td>
<td>No candidates available for confirmation</td>
</tr>
</tbody>
</table>
<h3>TMDb Errors (E3xx)</h3>
<table class="table">
<thead>
<tr>
<th>Code</th>
<th>HTTP</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>E301_TMDB_NO_KEY</code></td>
<td>400</td>
<td><code>TMDB_API_KEY</code> environment variable not set</td>
</tr>
<tr>
<td><code>E302_TMDB_UNREACHABLE</code></td>
<td>502</td>
<td>TMDb API unreachable or timed out</td>
</tr>
<tr>
<td><code>E303_TMDB_CACHE_NOT_FOUND</code></td>
<td>200</td>
<td>No local TMDb cache; run prefetch first</td>
</tr>
<tr>
<td><code>E304_TMDB_PROBE_FAILED</code></td>
<td>500</td>
<td>TMDb probe execution failed</td>
</tr>
<tr>
<td><code>E305_TMDB_MOVIE_NOT_FOUND</code></td>
<td>404</td>
<td>No matching TMDb movie found from filename</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>Momentry API 文件</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 40px; }
.container { max-width: 900px; margin: 0 auto; background: white; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); padding: 40px; }
h1 { font-size: 28px; margin-bottom: 8px; }
p.subtitle { color: #666; margin-bottom: 24px; }
table { width: 100%; border-collapse: collapse; }
tr { border-bottom: 1px solid #eee; }
tr:last-child { border: none; }
td { padding: 10px 0; }
td.cn { width: 140px; font-weight: 600; color: #333; }
td.en { color: #666; font-size: 14px; }
a { color: #0066cc; text-decoration: none; display: block; }
a:hover td { background: #f8f8f8; border-radius: 4px; }
</style>
</head>
<body>
<div class="container">
<h1>Momentry API 文件</h1>
<p class="subtitle">API 參考手冊 — 登入後可瀏覽各模組文件</p>
<table><tr onclick="window.location='11_error_codes.html'" style="cursor:pointer"><td class="cn">錯誤碼</td><td class="en">Error Codes</td></tr></table>
</div>
</body>
</html>

View File

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login - Momentry Docs</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; display: flex; justify-content: center; align-items: center; height: 100vh; }
.card { background: white; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); padding: 40px; width: 360px; }
h1 { font-size: 24px; margin-bottom: 24px; text-align: center; }
input { width: 100%; padding: 10px 12px; margin-bottom: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; }
button { width: 100%; padding: 10px; background: #0066cc; color: white; border: none; border-radius: 6px; font-size: 16px; cursor: pointer; }
button:hover { background: #0052a3; }
.error { color: #cc0000; font-size: 13px; margin-bottom: 12px; display: none; }
</style>
</head>
<body>
<div class="card">
<h1>Momentry Docs</h1>
<form id="loginForm">
<input type="text" id="username" placeholder="Username" value="demo" required>
<input type="password" id="password" placeholder="Password" value="demo" required>
<div class="error" id="error">Invalid credentials</div>
<button type="submit">Login</button>
</form>
</div>
<script>
document.getElementById('loginForm').onsubmit = async function(e) {
e.preventDefault();
const resp = await fetch('/api/v1/auth/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
username: document.getElementById('username').value,
password: document.getElementById('password').value
})
});
if (resp.ok) {
window.location.href = '/doc/index.html';
} else {
document.getElementById('error').style.display = 'block';
}
};
</script>
</body>
</html>