[FFmpeg-user] Audio captured via AVFoundation is unusable
Gyan Doshi
ffmpeg at gyani.pro
Wed Jun 4 10:09:05 EEST 2025
On 2025-06-04 03:20 am, FFmpeg via ffmpeg-user wrote:
>> With AVFoundation, sometimes audio parameters aren't initialized at start of capture. The OS initializes the audio very shortly afterwards, but ffmpeg uses the parameters advertised in the beginning, which will be incorrect.
> This definitely tracks with the behavior I'm witnessing.
>
>> I wrote a patch few years back to fix this - I'll find it and update it.
>> I'll post it if you can test it.
> That would be excellent, I'd be happy to test it.
Diff patch attached. Use `git apply` .
Initially test with
-f avfoundation \
-audio_probe_wait 2 \
-i ... \
Check till values of 15 or so.
Regards,
Gyan
-------------- next part --------------
From 06c626a01170d05fb5b67c0d3d9e89bfc385381f Mon Sep 17 00:00:00 2001
From: Gyan Doshi <ffmpeg at gyani.pro>
Date: Wed, 4 Jun 2025 12:31:08 +0530
Subject: [PATCH] lavd/avfoundation: allow delay for audio format probing
Set -audio_probe_wait X to probe format from frame #X
---
libavdevice/avfoundation.m | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index 6f15e2837e..4d609c10ae 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -121,6 +121,7 @@ typedef struct
int audio_signed_integer;
int audio_packed;
int audio_non_interleaved;
+ int audio_probe_wait;
int32_t *audio_buffer;
int audio_buffer_size;
@@ -685,7 +686,7 @@ static int get_audio_config(AVFormatContext *s)
}
// Take stream info from the first frame.
- while (ctx->audio_frames_captured < 1) {
+ while (ctx->audio_frames_captured < ctx->audio_probe_wait) {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
}
@@ -716,6 +717,13 @@ static int get_audio_config(AVFormatContext *s)
ctx->audio_packed = basic_desc->mFormatFlags & kAudioFormatFlagIsPacked;
ctx->audio_non_interleaved = basic_desc->mFormatFlags & kAudioFormatFlagIsNonInterleaved;
+ av_log(s, AV_LOG_VERBOSE, "Detected audio format:\n"
+ "mFormatID: %d | float: %d | s_int: %d | depth: %d | packed: %d | non_interleaved: %d \n"
+ "mSampleRate: %d | channels: %d | mBitsPerChannel: %d | audio_be: %d\n",
+ (int)basic_desc->mFormatID, ctx->audio_float, ctx->audio_signed_integer, ctx->audio_bits_per_sample, ctx->audio_packed,
+ ctx->audio_non_interleaved, (int)basic_desc->mSampleRate, (int)basic_desc->mChannelsPerFrame,
+ (int)basic_desc->mBitsPerChannel, ctx->audio_be);
+
if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
ctx->audio_float &&
ctx->audio_bits_per_sample == 32 &&
@@ -1285,6 +1293,7 @@ static const AVOption options[] = {
{ "capture_mouse_clicks", "capture the screen mouse clicks", offsetof(AVFContext, capture_mouse_clicks), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
{ "capture_raw_data", "capture the raw data from device connection", offsetof(AVFContext, capture_raw_data), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
{ "drop_late_frames", "drop frames that are available later than expected", offsetof(AVFContext, drop_late_frames), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
+ { "audio_probe_wait", "number of packets to wait for audio config probe", offsetof(AVFContext, audio_probe_wait), AV_OPT_TYPE_INT, {.i64=1}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
{ NULL },
};
--
2.49.0
More information about the ffmpeg-user
mailing list