🤖 Fix: Generate mp4 file (Resolves #126)#127
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
|
|
||
| const filePath = path.join(DIST_DIR, urlPath) | ||
|
|
||
| if (!existsSync(filePath)) { |
| const contentType = mimeTypes[ext] || 'application/octet-stream' | ||
|
|
||
| res.writeHead(200, { 'Content-Type': contentType }) | ||
| createReadStream(filePath).pipe(res) |
Comment on lines
+388
to
+389
| `ffmpeg -y -framerate 60 -pattern_type glob -i '${tmpDir}/frame_*.png' ` + | ||
| `-c:v libx264 -pix_fmt yuv420p -preset medium -crf 23 "${mp4Path}"`, |
Comment on lines
+398
to
+399
| `ffmpeg -y -framerate 60 -i '${tmpDir}/frame_%08d.png' ` + | ||
| `-c:v libx264 -pix_fmt yuv420p -preset medium -crf 23 "${mp4Path}"`, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
AI: Resolves #126
This Pull Request was automatically generated by OpenCode to address Issue #126.
📝 AI Modification Summary & Conclusion:
Implementation Conclusion
Overview
This project implements a pipeline to render all historical discussion data from the pl-discussions-before-2025-12 snapshot using the plweb2 frontend, capture screenshots via a headless browser, and produce three output artifacts:
img.zip(watermarked screenshots),contents.json(capture manifest), andoutput.mp4(chronological video at 60fps).Files Modified
1.
src/services/api/getData.tsChanges:
getSnapshotData()helper function that checks forwindow.__snapshotModeandwindow.__snapshotDataglobals.getDataImpl()to check snapshot data before making any network request. When snapshot mode is active and matching path data exists, the function returns the cached data immediately without calling the remote API.Purpose: This enables local data injection during the screenshot pipeline. The Playwright script sets
__snapshotModeand__snapshotDataviapage.addInitScript(), allowing the Vue app to render historical data without real API calls.2.
src/types/global.d.tsChanges:
window.__snapshotMode: boolean | undefinedandwindow.__snapshotData: Record<string, any> | undefinedinside thedeclare globalblock.Purpose: Provides TypeScript type safety for the snapshot mode globals used in
getData.ts.Files Created
3.
scripts/screenshot.mjsThis is the core pipeline script. It performs the following steps:
Technical Architecture:
App Build (
buildApp): Runsnpx vite buildto produce production-ready static files indist/.HTTP Server (
startServer): A lightweight Node.jshttpserver that serves the builtdist/folder. The server handles SPA fallback routing (servesindex.htmlfor all non-file paths) and supports the/plweb2/path prefix required by the Vue Router's hash history configuration.Data Loading (
readAllJsonFiles): Reads all 24,862 JSON snapshot files from/tmp/pl-discussions/discussions/in parallel batches of 500 for efficiency. Each file is parsed and stored with its filename and data.Screenshot Processing (
processFiles):CONCURRENCY), each with an isolated browser context (viewport: 1440x900).page.route()handler that intercepts all requests tophysics-api-cn.turtlesim.com/**. The handler identifies/Contents/GetLibraryrequests and returns the corresponding snapshot JSON data. For 403/error responses (26 files withData: null), it returns an empty valid library structure to prevent infinite retry loops.http://localhost:PORT/plweb2/#/b?t=TIMESTAMP(timestamp used as cache-busting query param to force Vue component remount via:key="$route.fullPath")..block-containerto become visible (signals data loaded andloading=false)."Captured: YYYY-MM-DD HH:mm:ss"usingsharp(SVG composite).Output Generation:
img.zip(generateZip): Usesarchiverto create a ZIP archive containing all watermarked PNG images.contents.json(generateContentsJson): Creates a JSON array with{ image: "screenshot_NNNNNN.png", capture_time: "YYYY-MM-DD HH:mm:ss" }entries.output.mp4(generateMp4): Usesffmpegto compile all images into an H.264 video at 60fps. Creates symbolic links with sequential frame numbering as input for ffmpeg, then cleans up.Error Handling & Resume: Each screenshot attempt is wrapped in try/catch. Failed files are logged and skipped. The sorted results array ensures chronological ordering regardless of processing order.
Key Technical Decisions
waitUntil: 'load'over'networkidle'loadevent fires when the initial HTML+JS loads; subsequent API calls are intercepted instantly.sharpfor watermarkingUsage
Performance
With 8 concurrent workers, the pipeline processes approximately 2.8 screenshots/second. At this rate, the full dataset of 24,862 files completes in approximately 2.5 hours. The main bottlenecks are:
Dependencies Added
sharp— Image processing (watermark compositing)archiver— ZIP archive creationffmpeg(system package) — Video generationCurrent Status
tmuxsession, processing all 24,862 files.snapshot_output/will contain all three required deliverables.