mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-27 00:05:39 +00:00
fix(recording): compact silent mic discontinuities
This commit is contained in:
@@ -5,10 +5,10 @@
|
||||
"helpers": {
|
||||
"wgc-capture": {
|
||||
"binaryName": "wgc-capture.exe",
|
||||
"binarySha256": "a0e2f0b98a903f89ab4706a56623f141604c3a311102e8914c2780745e94c635",
|
||||
"binarySha256": "88226bd499c820081a27264b40f37875d0949d9f921920738e05b7eaeb1a9e7d",
|
||||
"sourceDir": "electron/native/wgc-capture",
|
||||
"sourceFingerprint": "820d13741c659a0357d4d7944f3dbf4ce778b9716725b47ec088f573db0e7311",
|
||||
"updatedAt": "2026-05-06T13:15:19.804Z"
|
||||
"sourceFingerprint": "7190e148ede1fb1c573cc1866405d6345b0c35378a7e32499580bffacf1cc6d2",
|
||||
"updatedAt": "2026-05-06T16:09:49.253Z"
|
||||
},
|
||||
"cursor-monitor": {
|
||||
"binaryName": "cursor-monitor.exe",
|
||||
|
||||
Binary file not shown.
@@ -231,6 +231,8 @@ static void writeCompanionAudioTimingMetadata(
|
||||
metadataFile << ",\"insertedSilenceFrames\":" << capture.insertedSilenceFrames();
|
||||
metadataFile << ",\"compactedDiscontinuityCount\":" << capture.compactedDiscontinuityCount();
|
||||
metadataFile << ",\"compactedDiscontinuityFrames\":" << capture.compactedDiscontinuityFrames();
|
||||
metadataFile << ",\"compactedSilentDiscontinuityCount\":" << capture.compactedSilentDiscontinuityCount();
|
||||
metadataFile << ",\"compactedSilentDiscontinuityFrames\":" << capture.compactedSilentDiscontinuityFrames();
|
||||
const uint32_t discontinuityCount = capture.dataDiscontinuityCount();
|
||||
if (discontinuityCount > 0) {
|
||||
metadataFile << ",\"dataDiscontinuityCount\":" << discontinuityCount;
|
||||
@@ -448,7 +450,8 @@ int main(int argc, char* argv[]) {
|
||||
loopback.dataDiscontinuityCount() > 0 ||
|
||||
loopback.timestampErrorCount() > 0 ||
|
||||
loopback.gapFillCount() > 0 ||
|
||||
loopback.compactedDiscontinuityCount() > 0
|
||||
loopback.compactedDiscontinuityCount() > 0 ||
|
||||
loopback.compactedSilentDiscontinuityCount() > 0
|
||||
) {
|
||||
std::cerr << "WARNING: System audio timing metadata includes discontinuities="
|
||||
<< loopback.dataDiscontinuityCount()
|
||||
@@ -457,6 +460,8 @@ int main(int argc, char* argv[]) {
|
||||
<< " insertedSilenceFrames=" << loopback.insertedSilenceFrames()
|
||||
<< " compactedDiscontinuities=" << loopback.compactedDiscontinuityCount()
|
||||
<< " compactedDiscontinuityFrames=" << loopback.compactedDiscontinuityFrames()
|
||||
<< " compactedSilentDiscontinuities=" << loopback.compactedSilentDiscontinuityCount()
|
||||
<< " compactedSilentDiscontinuityFrames=" << loopback.compactedSilentDiscontinuityFrames()
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << "Audio path: " << config.audioOutputPath << std::endl;
|
||||
@@ -466,7 +471,8 @@ int main(int argc, char* argv[]) {
|
||||
micCapture.dataDiscontinuityCount() > 0 ||
|
||||
micCapture.timestampErrorCount() > 0 ||
|
||||
micCapture.gapFillCount() > 0 ||
|
||||
micCapture.compactedDiscontinuityCount() > 0
|
||||
micCapture.compactedDiscontinuityCount() > 0 ||
|
||||
micCapture.compactedSilentDiscontinuityCount() > 0
|
||||
) {
|
||||
std::cerr << "WARNING: Microphone timing metadata includes discontinuities="
|
||||
<< micCapture.dataDiscontinuityCount()
|
||||
@@ -475,6 +481,8 @@ int main(int argc, char* argv[]) {
|
||||
<< " insertedSilenceFrames=" << micCapture.insertedSilenceFrames()
|
||||
<< " compactedDiscontinuities=" << micCapture.compactedDiscontinuityCount()
|
||||
<< " compactedDiscontinuityFrames=" << micCapture.compactedDiscontinuityFrames()
|
||||
<< " compactedSilentDiscontinuities=" << micCapture.compactedSilentDiscontinuityCount()
|
||||
<< " compactedSilentDiscontinuityFrames=" << micCapture.compactedSilentDiscontinuityFrames()
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << "Mic path: " << config.micOutputPath << std::endl;
|
||||
|
||||
@@ -14,6 +14,7 @@ constexpr uint32_t kMinimumGapFillThresholdMs = 50;
|
||||
// Wireless headsets can flag short WASAPI discontinuities that are less audible
|
||||
// when compacted and later duration-corrected than when rendered as hard silence.
|
||||
constexpr uint32_t kDiscontinuityGapFillThresholdMs = 140;
|
||||
constexpr uint32_t kSilentDiscontinuityCompactThresholdMs = 40;
|
||||
constexpr uint32_t kBoundaryFadeInMs = 5;
|
||||
|
||||
int64_t queryPerformanceCounterHns() {
|
||||
@@ -197,6 +198,8 @@ bool WasapiCapture::start() {
|
||||
insertedSilenceFrames_ = 0;
|
||||
compactedDiscontinuityCount_ = 0;
|
||||
compactedDiscontinuityFrames_ = 0;
|
||||
compactedSilentDiscontinuityCount_ = 0;
|
||||
compactedSilentDiscontinuityFrames_ = 0;
|
||||
fadeInFramesRemaining_ = 0;
|
||||
writeWavHeader(outputFile_, 0);
|
||||
|
||||
@@ -478,8 +481,28 @@ void WasapiCapture::captureThread() {
|
||||
}
|
||||
|
||||
UINT32 totalSamples = numFrames * channels;
|
||||
const bool isSilentPacket = (flags & AUDCLNT_BUFFERFLAGS_SILENT) != 0;
|
||||
const uint32_t silentCompactThresholdFrames =
|
||||
(mixFormat_->nSamplesPerSec * kSilentDiscontinuityCompactThresholdMs) / 1000;
|
||||
if (
|
||||
hasDataDiscontinuity &&
|
||||
isSilentPacket &&
|
||||
framesWritten_.load() > 0 &&
|
||||
numFrames > 0 &&
|
||||
numFrames <= (silentCompactThresholdFrames > 0 ? silentCompactThresholdFrames : 1)
|
||||
) {
|
||||
compactedSilentDiscontinuityCount_.fetch_add(1);
|
||||
compactedSilentDiscontinuityFrames_.fetch_add(numFrames);
|
||||
captureClient_->ReleaseBuffer(numFrames);
|
||||
hr = captureClient_->GetNextPacketSize(&packetLength);
|
||||
if (FAILED(hr)) {
|
||||
std::cerr << "WASAPI: GetNextPacketSize failed hr=0x" << std::hex << hr << std::dec << std::endl;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & AUDCLNT_BUFFERFLAGS_SILENT) {
|
||||
if (isSilentPacket) {
|
||||
pcmBuffer.assign(totalSamples, 0);
|
||||
} else if (isFloat && bitsPerSample == 32 && sourceBytesPerSample >= 4) {
|
||||
pcmBuffer.resize(totalSamples);
|
||||
|
||||
@@ -30,6 +30,8 @@ public:
|
||||
uint64_t insertedSilenceFrames() const { return insertedSilenceFrames_.load(); }
|
||||
uint32_t compactedDiscontinuityCount() const { return compactedDiscontinuityCount_.load(); }
|
||||
uint64_t compactedDiscontinuityFrames() const { return compactedDiscontinuityFrames_.load(); }
|
||||
uint32_t compactedSilentDiscontinuityCount() const { return compactedSilentDiscontinuityCount_.load(); }
|
||||
uint64_t compactedSilentDiscontinuityFrames() const { return compactedSilentDiscontinuityFrames_.load(); }
|
||||
|
||||
private:
|
||||
bool initializeCommon();
|
||||
@@ -65,5 +67,7 @@ private:
|
||||
std::atomic<uint64_t> insertedSilenceFrames_{0};
|
||||
std::atomic<uint32_t> compactedDiscontinuityCount_{0};
|
||||
std::atomic<uint64_t> compactedDiscontinuityFrames_{0};
|
||||
std::atomic<uint32_t> compactedSilentDiscontinuityCount_{0};
|
||||
std::atomic<uint64_t> compactedSilentDiscontinuityFrames_{0};
|
||||
std::atomic<uint32_t> fadeInFramesRemaining_{0};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user