Repository navigation
Conversation
With the modern video message pipeline, recording a round video stays at 0:00 when a headset microphone (wired EarPods or Bluetooth) is the input (bugs.telegram.org/c/66487, c/66930). In multi-camera mode CameraNeo added the microphone without connections and connected every audio port of the input to the audio data output by hand. VideoRecorder starts writing only after the first audio sample has created the audio track, with no timeout, so if that connection delivers nothing the recording never starts. Add the microphone input and the audio output with implicit connections in both modes, as the legacy camera does in the same multi-camera session, and let the session pick the port for the current route.
VideoRecorder encodes audio as AAC at 64 kbps with the microphone's own sample rate and channel count. A headset microphone on the Bluetooth call profile delivers 8 or 16 kHz, where the system AAC encoder allows at most 24 or 48 kbps for mono. canApply(outputSettings:) still accepts 64 kbps, startWriting() then fails with "Cannot Encode Media" (-11861), and the camera closes with an error. Ask the encoder for the bit rates it accepts at the actual sample rate and channel count, and use its maximum when that is below 64 kbps. Every other format keeps 64 kbps.
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.
Fixes https://bugs.telegram.org/c/66487 (and the merged https://bugs.telegram.org/c/66930): with the modern video message pipeline, a round video never starts recording when a headset microphone is the input. The camera keeps showing the loading animation and the timer stays at 0:00. Reported with Bluetooth earbuds and with wired EarPods, both on iPhones that support multi-camera capture.
Cause
Round videos use
AVCaptureMultiCamSessionon every device that supports it (isDualCameraSupported(forRoundVideo: true)). In that modeCameraNeo.configureAudio()added the microphone input and the audio data output with no connections, then connected every audio port of the input to the output in one manualAVCaptureConnection.VideoRecorderonly starts writing once the first audio sample has created the AAC writer input (tryStartWritingrequires!hasAudio || audioInput != nil), and nothing gives up after a timeout. The duration shown in the UI only advances once writing has started. So if the audio connection delivers no samples, the recording stays in.armingforever, which is exactly the reported symptom. A failure would close the screen instead: the screen's error handler callscompletion(nil, …).The built-in microphone exposes several positional ports in a multi-camera session, so the manual connection works there. With a headset microphone (pinned as the preferred input by
ManagedAudioSessionwhen a headset is connected) the input's ports are different, and the manual connection most likely delivers nothing. Voice messages and the legacy round-video pipeline use the same audio session and keep working with the same headsets.A second problem sits behind the first one and only shows up once audio flows.
VideoRecorderencodes AAC at a fixed 64 kbps with the microphone's own sample rate and channel count. A Bluetooth headset microphone uses the call profile, which delivers 8 or 16 kHz, and the system AAC encoder allows at most 24 kbps (8 kHz mono) or 48 kbps (16 kHz mono) there.canApply(outputSettings:)still accepts 64 kbps;startWriting()then fails with "Cannot Encode Media" (AVFoundationErrorDomain -11861, underlying-12651), and the camera closes with an error. Measured with the system AAC encoder on macOS:The legacy recorder doesn't hit this because it starts from
recommendedAudioSettingsForAssetWriter.Change
1. Microphone connection (
CameraNeo.swift)configureAudio()adds the microphone input and the audio output with implicit connections (addInput/addOutput) in both modes, so the session picks the port for the current route. This is what the legacy camera has always done, in the sameAVCaptureMultiCamSession(CameraInput.configureAudioInput,CameraOutput.configure).Why this doesn't affect anything else:
automaticallyConnect: falsein multi-camera mode.configureSession().audioOutputIdentity), as before.The one change in behaviour: with the built-in microphone in multi-camera mode, the session now picks the port instead of all positional ports feeding one output. That is what the legacy pipeline records.
2. AAC bit rate (
VideoRecorder.swift)addAudioInputIfPossibleasks the AAC encoder for the bit rates it accepts at the actual sample rate and channel count (kAudioConverterApplicableEncodeBitRates) and uses its maximum when that is below 64 kbps. In practice only 8 and 16 kHz mono are lowered (to 24 and 48 kbps); every other format, including the built-in microphone at 44.1/48 kHz, keeps 64 kbps. If the query fails, the settings are unchanged.Testing
debug_sim_arm64).AVAssetWriterstarts with the capped rate at 8 and 16 kHz (mono and stereo) where 64 kbps fails. Encoding 2 s of PCM through the writer at 24 kbps / 8 kHz and 48 kbps / 16 kHz completes.Not in this PR