Repository navigation
feat(protocol,onebot): raise video size limit to 1.5GB with Highway-first fallback - #35
Conversation
审阅者指南将视频上传的软限制从 100MB 提升至 4GB,并加入两层回退机制:首先尝试使用 Highway 上传(最高 4GB),如果失败,则在群聊和私聊消息中降级为文件上传;同时新增用于检测大小的辅助方法,并在 element 构建和 OneBot 发送路径中增加针对性的错误处理。 私聊视频上传降级为文件的序列图sequenceDiagram
actor Client
participant OneBot as sendPrivateMessage
participant MsgAPI as bridge.apis.message
participant FileAPI as bridge.apis.file
Client->>OneBot: sendPrivateMessage(userId, elements)
OneBot->>OneBot: split elements into allFileElements & nonFileElements
alt nonFileElements not empty
OneBot->>MsgAPI: sendPrivate(userId, nonFileElements)
MsgAPI-->>OneBot: error (video upload failed)
OneBot->>OneBot: getVideoSourceSize(videoElement)
alt size > MAX_VIDEO_SIZE
OneBot->>OneBot: log.warn fallback to file upload
OneBot->>OneBot: convert video element to file MessageElement
OneBot->>OneBot: update allFileElements & nonFileElements
opt nonFileElements still not empty
OneBot->>MsgAPI: sendPrivate(userId, nonFileElements)
MsgAPI-->>OneBot: lastReceipt
OneBot->>OneBot: logSentMessage(false, userId, nonFileElements)
end
else no large video element
OneBot-->>Client: rethrow error
end
end
opt allFileElements not empty
OneBot->>FileAPI: uploadPrivate / sendC2cFile(allFileElements)
FileAPI-->>OneBot: file upload receipts
end
OneBot-->>Client: final lastReceipt and file results
文件级变更
技巧与命令与 Sourcery 交互
自定义你的体验访问你的 dashboard 以:
获取帮助Original review guide in EnglishReviewer's GuideRaises the video upload soft limit from 100MB to 4GB with a two-layer fallback: first attempting Highway upload up to 4GB, and on failure degrading to file uploads for group and private messages, including size introspection helpers and targeted error handling in element building and OneBot message sending paths. Sequence diagram for private video upload fallback to filesequenceDiagram
actor Client
participant OneBot as sendPrivateMessage
participant MsgAPI as bridge.apis.message
participant FileAPI as bridge.apis.file
Client->>OneBot: sendPrivateMessage(userId, elements)
OneBot->>OneBot: split elements into allFileElements & nonFileElements
alt nonFileElements not empty
OneBot->>MsgAPI: sendPrivate(userId, nonFileElements)
MsgAPI-->>OneBot: error (video upload failed)
OneBot->>OneBot: getVideoSourceSize(videoElement)
alt size > MAX_VIDEO_SIZE
OneBot->>OneBot: log.warn fallback to file upload
OneBot->>OneBot: convert video element to file MessageElement
OneBot->>OneBot: update allFileElements & nonFileElements
opt nonFileElements still not empty
OneBot->>MsgAPI: sendPrivate(userId, nonFileElements)
MsgAPI-->>OneBot: lastReceipt
OneBot->>OneBot: logSentMessage(false, userId, nonFileElements)
end
else no large video element
OneBot-->>Client: rethrow error
end
end
opt allFileElements not empty
OneBot->>FileAPI: uploadPrivate / sendC2cFile(allFileElements)
FileAPI-->>OneBot: file upload receipts
end
OneBot-->>Client: final lastReceipt and file results
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
📝 WalkthroughWalkthrough本次修改调整了视频上传的大小校验阈值:新增硬上限,超过软上限时改为告警并继续处理,同时新增获取视频源大小的函数。视频元素在群聊上传失败时可回退为文件元素。私聊发送流程在上传失败时会识别超大视频并转为文件元素后继续发送。 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Hey - 我发现了 2 个问题,并给出了一些总体反馈:
- 在
makeVideoElem中,你直接使用了console.warn,而该模块/调用栈的其他部分都依赖结构化日志工具(例如moduleLog/log);建议将这个 warning 通过现有的日志工具输出,以保持一致性和可配置性。 getVideoSourceSize在消息发送路径中(被sendPrivateMessage使用)执行了同步的fs.existsSync/fs.statSync调用,对于大型或较慢的文件系统,这可能会阻塞事件循环;建议改用异步的fs.promises版本,或者把这部分工作从热点路径中移出。
供 AI Agent 使用的提示
Please address the comments from this code review:
## Overall Comments
- In `makeVideoElem` you’re using `console.warn` directly while the rest of the module/stack relies on structured loggers (e.g. `moduleLog`/`log`); consider routing this warning through the existing logging utility for consistency and configurability.
- `getVideoSourceSize` performs synchronous `fs.existsSync`/`fs.statSync` calls in the message send path (used by `sendPrivateMessage`), which can block the event loop for large or slow filesystems; consider switching to the async `fs.promises` variants or deferring this work off the hot path.
## Individual Comments
### Comment 1
<location path="packages/protocol/src/element-builder.ts" line_range="391-393" />
<code_context>
+ try {
+ lastReceipt = await ref.bridge.apis.message.sendPrivate(userId, nonFileElements);
+ logSentMessage(false, userId, nonFileElements);
+ } catch (err) {
+ // Highway upload failed — check if a large video element triggered it
+ // and fall back to file upload for that element (private messages
</code_context>
<issue_to_address>
**suggestion:** Use the existing logging mechanism instead of `console.warn` for consistency and configurability.
In this package we standardize on the module logger rather than `console.*`. Please switch this warning to `moduleLog.warn` (or the equivalent here) so log formatting, levels, routing, and observability remain consistent with the rest of the system.
</issue_to_address>
### Comment 2
<location path="packages/onebot/src/modules/message-actions.ts" line_range="552-555" />
<code_context>
+ // Highway upload failed — check if a large video element triggered it
+ // and fall back to file upload for that element (private messages
+ // cannot carry file elements through the element pipeline).
+ const videoIdx = nonFileElements.findIndex(e => {
+ if (e.type !== 'video') return false;
+ const sz = getVideoSourceSize(e);
+ return sz !== null && sz > MAX_VIDEO_SIZE;
+ });
+ if (videoIdx >= 0) {
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Size-based fallback may miss some large-video failures when `getVideoSourceSize` returns null.
Because the fallback only checks `getVideoSourceSize` against `MAX_VIDEO_SIZE`, any video whose size can’t be inferred (`sz === null`) will never trigger the fallback—even if the upload actually failed due to a size limit. If the bridge exposes a specific error code or message for size-related failures, consider also using that signal so the fallback covers these remote-only cases.
Suggested implementation:
```typescript
// Highway upload failed — check if a large video element triggered it
// and fall back to file upload for that element (private messages
// cannot carry file elements through the element pipeline).
// Also consider explicit size-limit errors from the bridge so that
// videos whose size can't be inferred locally can still trigger
// the fallback.
const isSizeLimitError =
err instanceof Error &&
/size limit|too large|413/i.test(err.message);
const videoIdx = nonFileElements.findIndex(e => {
if (e.type !== 'video') return false;
const sz = getVideoSourceSize(e);
if (sz === null) {
// If we know the remote failed with a size-limit error, treat
// size-unknown videos as candidates for fallback as well.
return isSizeLimitError;
}
return sz > MAX_VIDEO_SIZE;
});
```
If the bridge exposes a more specific way to detect size-related failures (for example, a structured error type with a `code` like `HIGHWAY_SIZE_LIMIT` or a boolean flag), replace the `isSizeLimitError` heuristic with that canonical check, e.g.:
```ts
const isSizeLimitError =
typeof err === 'object' &&
err !== null &&
'code' in err &&
(err as any).code === 'HIGHWAY_SIZE_LIMIT';
```
This should be aligned with however other parts of the codebase detect Highway size-limit errors.
</issue_to_address>帮我变得更有用!请对每条评论点 👍 或 👎,我会根据你的反馈改进后续的评审。
Original comment in English
Hey - I've found 2 issues, and left some high level feedback:
- In
makeVideoElemyou’re usingconsole.warndirectly while the rest of the module/stack relies on structured loggers (e.g.moduleLog/log); consider routing this warning through the existing logging utility for consistency and configurability. getVideoSourceSizeperforms synchronousfs.existsSync/fs.statSynccalls in the message send path (used bysendPrivateMessage), which can block the event loop for large or slow filesystems; consider switching to the asyncfs.promisesvariants or deferring this work off the hot path.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `makeVideoElem` you’re using `console.warn` directly while the rest of the module/stack relies on structured loggers (e.g. `moduleLog`/`log`); consider routing this warning through the existing logging utility for consistency and configurability.
- `getVideoSourceSize` performs synchronous `fs.existsSync`/`fs.statSync` calls in the message send path (used by `sendPrivateMessage`), which can block the event loop for large or slow filesystems; consider switching to the async `fs.promises` variants or deferring this work off the hot path.
## Individual Comments
### Comment 1
<location path="packages/protocol/src/element-builder.ts" line_range="391-393" />
<code_context>
+ try {
+ lastReceipt = await ref.bridge.apis.message.sendPrivate(userId, nonFileElements);
+ logSentMessage(false, userId, nonFileElements);
+ } catch (err) {
+ // Highway upload failed — check if a large video element triggered it
+ // and fall back to file upload for that element (private messages
</code_context>
<issue_to_address>
**suggestion:** Use the existing logging mechanism instead of `console.warn` for consistency and configurability.
In this package we standardize on the module logger rather than `console.*`. Please switch this warning to `moduleLog.warn` (or the equivalent here) so log formatting, levels, routing, and observability remain consistent with the rest of the system.
</issue_to_address>
### Comment 2
<location path="packages/onebot/src/modules/message-actions.ts" line_range="552-555" />
<code_context>
+ // Highway upload failed — check if a large video element triggered it
+ // and fall back to file upload for that element (private messages
+ // cannot carry file elements through the element pipeline).
+ const videoIdx = nonFileElements.findIndex(e => {
+ if (e.type !== 'video') return false;
+ const sz = getVideoSourceSize(e);
+ return sz !== null && sz > MAX_VIDEO_SIZE;
+ });
+ if (videoIdx >= 0) {
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Size-based fallback may miss some large-video failures when `getVideoSourceSize` returns null.
Because the fallback only checks `getVideoSourceSize` against `MAX_VIDEO_SIZE`, any video whose size can’t be inferred (`sz === null`) will never trigger the fallback—even if the upload actually failed due to a size limit. If the bridge exposes a specific error code or message for size-related failures, consider also using that signal so the fallback covers these remote-only cases.
Suggested implementation:
```typescript
// Highway upload failed — check if a large video element triggered it
// and fall back to file upload for that element (private messages
// cannot carry file elements through the element pipeline).
// Also consider explicit size-limit errors from the bridge so that
// videos whose size can't be inferred locally can still trigger
// the fallback.
const isSizeLimitError =
err instanceof Error &&
/size limit|too large|413/i.test(err.message);
const videoIdx = nonFileElements.findIndex(e => {
if (e.type !== 'video') return false;
const sz = getVideoSourceSize(e);
if (sz === null) {
// If we know the remote failed with a size-limit error, treat
// size-unknown videos as candidates for fallback as well.
return isSizeLimitError;
}
return sz > MAX_VIDEO_SIZE;
});
```
If the bridge exposes a more specific way to detect size-related failures (for example, a structured error type with a `code` like `HIGHWAY_SIZE_LIMIT` or a boolean flag), replace the `isSizeLimitError` heuristic with that canonical check, e.g.:
```ts
const isSizeLimitError =
typeof err === 'object' &&
err !== null &&
'code' in err &&
(err as any).code === 'HIGHWAY_SIZE_LIMIT';
```
This should be aligned with however other parts of the codebase detect Highway size-limit errors.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| } catch (err) { | ||
| if (isGroup && element.fileId) { | ||
| console.warn('[ElemBuilder] video upload failed, falling back to file element: %s', err instanceof Error ? err.message : String(err)); |
There was a problem hiding this comment.
suggestion: 为了保持一致性和可配置性,请使用现有的日志机制,而不是 console.warn。
在这个包里我们标准化使用模块级日志器,而不是 console.*。请将此处的 warning 切换为 moduleLog.warn(或此处的等价实现),这样日志的格式、级别、路由和可观测性就能与系统中其他部分保持一致。
Original comment in English
suggestion: Use the existing logging mechanism instead of console.warn for consistency and configurability.
In this package we standardize on the module logger rather than console.*. Please switch this warning to moduleLog.warn (or the equivalent here) so log formatting, levels, routing, and observability remain consistent with the rest of the system.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/protocol/src/highway/video-upload.ts (1)
291-303: 🩺 Stability & Availability | 🟠 Major把视频读取改成流式,或把硬上限降到 2GiB 以下
fs.readFileSync(local)仍会把整段视频一次性装入内存;后续computeHashes(staged.bytes)和computeVideoSha1Blocks(staged.bytes)也都是基于这份完整字节数组处理,SHA1_STREAM_BLOCK_SIZE只是分块计算,不会避免 OOM。fs.readFileSync本身也有约 2GiB 的单次读取上限,所以MAX_VIDEO_SIZE_HARD = 4GiB实际不可达。建议改成流式读取/流式 SHA1,或者把硬上限调到明显低于 2GiB 的安全值。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/protocol/src/highway/video-upload.ts` around lines 291 - 303, The upload staging path in video-upload.ts still loads the entire file into memory via the local file handling in the upload helper, so fix this by either switching the staging/hash flow to stream-based processing or lowering the hard size limit to a safe value below the single-read ceiling. Update the logic around the function that returns staged video bytes, and ensure downstream consumers like computeHashes and computeVideoSha1Blocks do not require a full Uint8Array if you choose the streaming approach.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/onebot/src/modules/message-actions.ts`:
- Around line 557-568: The catch in message sending is too broad and treats any
`sendPrivate` failure as a large-video highway upload failure. Update the
fallback logic in `message-actions.ts` around the `sendPrivate` call and the
`videoIdx`/`findIndex` handling so it only retries as file upload when the error
clearly indicates highway/too-large upload failure, and otherwise rethrow the
original error. If multiple oversized local videos can appear, adjust the
`nonFileElements` processing to handle all matching video elements rather than
only the first one.
- Around line 552-556: The video fallback check in message-actions.ts only
triggers when getVideoSourceSize returns a known size above MAX_VIDEO_SIZE, so
remote http(s) videos with null size are skipped after sendPrivate fails. Update
the video handling around nonFileElements.findIndex (and the related sendPrivate
fallback path) to also treat “video present but size unknown” as a fallback
case, or ensure the video parser populates fileSize before this check so remote
large videos can fall back correctly.
---
Outside diff comments:
In `@packages/protocol/src/highway/video-upload.ts`:
- Around line 291-303: The upload staging path in video-upload.ts still loads
the entire file into memory via the local file handling in the upload helper, so
fix this by either switching the staging/hash flow to stream-based processing or
lowering the hard size limit to a safe value below the single-read ceiling.
Update the logic around the function that returns staged video bytes, and ensure
downstream consumers like computeHashes and computeVideoSha1Blocks do not
require a full Uint8Array if you choose the streaming approach.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 56df6d80-67db-46d7-a25f-4207ea8caa19
📒 Files selected for processing (3)
packages/onebot/src/modules/message-actions.tspackages/protocol/src/element-builder.tspackages/protocol/src/highway/video-upload.ts
d0cc6bd to
e44ec93
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/protocol/src/highway/video-upload.ts`:
- Around line 35-36: The hard-limit constant, the error messages, and the PR
target are inconsistent in the video upload flow. In video-upload.ts, reconcile
MAX_VIDEO_SIZE_HARD with the intended limit (1.5GB or 4GB), then update the
validation/error text in the upload checks and the related helpers so they all
derive from the same constant instead of hardcoding 4096 MB. Use
MAX_VIDEO_SIZE_HARD as the single source of truth in the functions that emit the
size-limit errors to keep the message and behavior aligned.
- Line 305: The video upload path still does full in-memory reads and hashing,
causing peak memory to scale with the size limit. Update the flow around
stageVideoSource, loadBinarySource, computeHashes, and computeVideoSha1Blocks to
use streaming or chunked processing instead of fs.readFileSync/full Uint8Array
accumulation, and avoid extra copies when writing the temp file and hashing. If
full buffering must remain, re-evaluate MAX_VIDEO_SIZE_HARD against the
deployment memory budget.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a14466ef-32e6-438a-ba64-6039a6b64331
📒 Files selected for processing (3)
packages/onebot/src/modules/message-actions.tspackages/protocol/src/element-builder.tspackages/protocol/src/highway/video-upload.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/protocol/src/element-builder.ts
- packages/onebot/src/modules/message-actions.ts
| } | ||
|
|
||
| const loaded = await loadBinarySource(source, 'video', MAX_VIDEO_SIZE); | ||
| const loaded = await loadBinarySource(source, 'video', MAX_VIDEO_SIZE_HARD); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major
🧩 Analysis chain
🌐 Web query:
Node.js buffer.constants.MAX_LENGTH value on 64-bit, and maximum size of Buffer / Uint8Array
💡 Result:
In Node.js, the value of buffer.constants.MAX_LENGTH has evolved alongside updates to the V8 engine [1]. On 64-bit systems, as of Node.js v22.0.0 and later (which includes V8 12.4 and newer), buffer.constants.MAX_LENGTH is 8 PiB (2^53 - 1 bytes, or exactly 9,007,199,254,740,991 bytes) [1]. Prior to Node.js v22.0.0, the limit was 4 GiB (2^32 bytes) [1]. Buffer instances in Node.js are subclasses of Uint8Array [2][3]. Consequently, the maximum size allowed for a Buffer is governed by this same constant [4][2]. Attempting to allocate a Buffer or Uint8Array larger than buffer.constants.MAX_LENGTH will result in an ERR_OUT_OF_RANGE error [4][2]. Note that while the theoretical V8 limit may be very large, practical limits on memory allocation and system architecture may still affect the actual maximum size you can successfully allocate in a real-world environment.
Citations:
- 1: doc: update
buffer.constants.MAX_LENGTHsize nodejs/node#54207 - 2: https://github.com/nodejs/node/blob/main/doc/api/buffer.md
- 3: https://nodejs.org/docs/latest-v26.x/api/buffer.html
- 4: https://nodejs.org/api/buffer.html
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the relevant file and surrounding helpers.
git ls-files packages/protocol/src/highway/video-upload.ts
echo '--- outline ---'
ast-grep outline packages/protocol/src/highway/video-upload.ts --view expanded
echo '--- line count ---'
wc -l packages/protocol/src/highway/video-upload.ts
echo '--- relevant slices ---'
sed -n '1,260p' packages/protocol/src/highway/video-upload.ts | cat -n
echo '--- second slice ---'
sed -n '260,420p' packages/protocol/src/highway/video-upload.ts | cat -nRepository: Stlara-F/SnowLuma
Length of output: 18529
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect helper implementations referenced by the review comment.
rg -n "loadBinarySource|stageVideoSource|computeHashes|computeVideoSha1Blocks|MAX_VIDEO_SIZE_HARD" packages/protocol/src -SRepository: Stlara-F/SnowLuma
Length of output: 2824
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check Node limit semantics with a small read-only probe if node is available.
node - <<'JS'
const { constants } = require('buffer');
console.log(JSON.stringify({
node: process.version,
MAX_LENGTH: constants.MAX_LENGTH,
MAX_STRING_LENGTH: constants.MAX_STRING_LENGTH,
}));
JSRepository: Stlara-F/SnowLuma
Length of output: 235
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read only the most relevant regions once outputs are available.
sed -n '1,220p' packages/protocol/src/highway/video-upload.ts | cat -n
sed -n '220,380p' packages/protocol/src/highway/video-upload.ts | cat -nRepository: Stlara-F/SnowLuma
Length of output: 14213
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the package's Node engine and the relevant implementation paths.
git ls-files package.json packages/protocol/package.json
echo '--- package.json / engine hints ---'
for f in package.json packages/protocol/package.json; do
if [ -f "$f" ]; then
echo "### $f"
rg -n '"engines"|"node"|MAX_VIDEO_SIZE_HARD|loadBinarySource|stageVideoSource|computeHashes|computeVideoSha1Blocks' "$f" -n -S || true
fi
doneRepository: Stlara-F/SnowLuma
Length of output: 327
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect loadBinarySource / computeHashes to confirm memory behavior and copies.
sed -n '1,280p' packages/protocol/src/highway/utils.ts | cat -nRepository: Stlara-F/SnowLuma
Length of output: 11951
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Probe Node's Buffer/Uint8Array limits against the repo's engine floor.
node - <<'JS'
const { constants } = require('buffer');
console.log(JSON.stringify({
node: process.version,
maxLength: constants.MAX_LENGTH,
maxTypedArrayLength: constants.MAX_LENGTH, // Buffer and Uint8Array share the same practical bound here
}));
JSRepository: Stlara-F/SnowLuma
Length of output: 243
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Confirm the exact source lines that materialize bytes in memory.
rg -n "readFileSync|Buffer\.from\(|new Uint8Array\(|loadBinarySource\(" packages/protocol/src/highway -SRepository: Stlara-F/SnowLuma
Length of output: 5203
这里仍然是全量读入 + 全量 hash,峰值内存会随上限一起抬高。
本地路径在 stageVideoSource 里仍是 fs.readFileSync,远端路径也会在 loadBinarySource 里累积成完整 Uint8Array;后面还要再写临时文件并跑 computeHashes / computeVideoSha1Blocks。当前 Node 22+ 的 Buffer / Uint8Array 长度上限已远高于 4GB,主要风险是 OOM 和额外拷贝开销;建议改成流式 hash / 分块处理,或把上限与部署内存配额重新对齐。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/protocol/src/highway/video-upload.ts` at line 305, The video upload
path still does full in-memory reads and hashing, causing peak memory to scale
with the size limit. Update the flow around stageVideoSource, loadBinarySource,
computeHashes, and computeVideoSha1Blocks to use streaming or chunked processing
instead of fs.readFileSync/full Uint8Array accumulation, and avoid extra copies
when writing the temp file and hashing. If full buffering must remain,
re-evaluate MAX_VIDEO_SIZE_HARD against the deployment memory budget.
…back Round 3: fix hardcoded 4096 MB in error messages - Use MAX_VIDEO_SIZE_HARD constant instead of hardcoded 4096 MB - Both throw sites now derive limit from the same constant
e44ec93 to
2f203a6
Compare
概述
对大于 100MB 小于 1.5GB 的视频上传做两层兜底:不再硬拒绝(throw),改为警告后先用 Highway 尝试上传;若 Highway 失败,自动降级为文件上传。
变更清单
设计决策
Review 修复记录
测试验证
自检