diff --git a/electron/native/bin/win32-x64/helpers-manifest.json b/electron/native/bin/win32-x64/helpers-manifest.json index bbcef557..d89ffe42 100644 --- a/electron/native/bin/win32-x64/helpers-manifest.json +++ b/electron/native/bin/win32-x64/helpers-manifest.json @@ -5,10 +5,10 @@ "helpers": { "wgc-capture": { "binaryName": "wgc-capture.exe", - "binarySha256": "4f8873abbff58add37672114184c154dee838939ee8f2b7df45d658d078af28c", + "binarySha256": "a04ecf49a5c0b9b92dfb9cd3aa1468178f7a144ac8b78b433e99b34425e35eac", "sourceDir": "electron/native/wgc-capture", - "sourceFingerprint": "6f725fad6eb515d81b2d553ec45ddbf7c681d2725bba48f0c0722ce00166d967", - "updatedAt": "2026-05-09T00:49:28.306Z" + "sourceFingerprint": "ef3602f1641538a9a19def9da84f1fcd8e37eb53f3e55c1ddf46f26ba75eb54c", + "updatedAt": "2026-05-22T08:56:01.149Z" }, "cursor-monitor": { "binaryName": "cursor-monitor.exe", diff --git a/electron/native/bin/win32-x64/wgc-capture.exe b/electron/native/bin/win32-x64/wgc-capture.exe index 37de4c9c..87fed123 100644 Binary files a/electron/native/bin/win32-x64/wgc-capture.exe and b/electron/native/bin/win32-x64/wgc-capture.exe differ diff --git a/electron/native/wgc-capture/src/mf_encoder.cpp b/electron/native/wgc-capture/src/mf_encoder.cpp index 1a89b21e..b84eacba 100644 --- a/electron/native/wgc-capture/src/mf_encoder.cpp +++ b/electron/native/wgc-capture/src/mf_encoder.cpp @@ -227,6 +227,12 @@ bool MFEncoder::writeFrame(ID3D11Texture2D* texture, int64_t timestampHns) { context_->Unmap(stagingTexture_.Get(), 0); + // WGC may stop delivering frames while the scene is static; keep the MP4 + // timeline continuous by repeating the previous frame before writing a new one. + if (!lastFrameBuffer_.empty() && !extendLastFrameToLocked(timestampHns)) { + return false; + } + bool wroteSample = writeNv12SampleLocked(nv12Buffer_, timestampHns); if (wroteSample) { lastFrameBuffer_ = nv12Buffer_; @@ -238,19 +244,29 @@ bool MFEncoder::writeFrame(ID3D11Texture2D* texture, int64_t timestampHns) { bool MFEncoder::extendLastFrameTo(int64_t timestampHns) { std::lock_guard lock(mutex_); + return extendLastFrameToLocked(timestampHns); +} + +bool MFEncoder::extendLastFrameToLocked(int64_t timestampHns) { if (!initialized_ || !sinkWriter_) return false; if (lastFrameBuffer_.empty()) return false; + if (lastSampleTimeHns_ < 0) return false; const int64_t frameDurationHns = 10000000LL / fps_; - if (lastSampleTimeHns_ >= 0 && timestampHns <= lastSampleTimeHns_ + frameDurationHns) { + if (frameDurationHns <= 0) return false; + if (timestampHns <= lastSampleTimeHns_ + frameDurationHns) { return true; } - if (!writeNv12SampleLocked(lastFrameBuffer_, timestampHns)) { - return false; + int64_t nextSampleTimeHns = lastSampleTimeHns_ + frameDurationHns; + while (nextSampleTimeHns + frameDurationHns <= timestampHns) { + if (!writeNv12SampleLocked(lastFrameBuffer_, nextSampleTimeHns)) { + return false; + } + lastSampleTimeHns_ = nextSampleTimeHns; + nextSampleTimeHns += frameDurationHns; } - lastSampleTimeHns_ = timestampHns; return true; } diff --git a/electron/native/wgc-capture/src/mf_encoder.h b/electron/native/wgc-capture/src/mf_encoder.h index 48fdeaad..2c25da02 100644 --- a/electron/native/wgc-capture/src/mf_encoder.h +++ b/electron/native/wgc-capture/src/mf_encoder.h @@ -24,6 +24,7 @@ public: bool finalize(); private: + bool extendLastFrameToLocked(int64_t timestampHns); bool writeNv12SampleLocked(const std::vector& frameBuffer, int64_t timestampHns); ComPtr sinkWriter_;