Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions crates/recording/src/feeds/microphone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ impl MicrophoneFeed {
fn get_usable_device(device: Device) -> Option<(String, Device, SupportedStreamConfig)> {
let device_name_for_logging = device.name().ok();

let preferred_rate = cpal::SampleRate(48_000);

let result = device
.supported_input_configs()
.map_err(|error| {
Expand All @@ -149,6 +151,16 @@ fn get_usable_device(device: Device) -> Option<(String, Device, SupportedStreamC
.then(b.max_sample_rate().cmp(&a.max_sample_rate()))
});

// First try to find a config that natively supports 48 kHz so we
// don't have to rely on resampling later.
if let Some(config) = configs.iter().find(|config| {
ffmpeg_sample_format_for(config.sample_format()).is_some()
&& config.min_sample_rate().0 <= preferred_rate.0
&& config.max_sample_rate().0 >= preferred_rate.0
}) {
return Some(config.clone().with_sample_rate(preferred_rate));
}

configs.into_iter().find_map(|config| {
ffmpeg_sample_format_for(config.sample_format())
.map(|_| config.with_sample_rate(select_sample_rate(&config)))
Expand Down
76 changes: 49 additions & 27 deletions crates/recording/src/sources/audio_mixer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,29 +68,46 @@ impl AudioMixerBuilder {
pub fn build(self, output: mpsc::Sender<AudioFrame>) -> Result<AudioMixer, ffmpeg::Error> {
let mut filter_graph = ffmpeg::filter::Graph::new();

let mut abuffers = self
.sources
.iter()
.enumerate()
.map(|(i, source)| {
let info = &source.info;
let args = format!(
"time_base={}:sample_rate={}:sample_fmt={}:channel_layout=0x{:x}",
info.time_base,
info.rate(),
info.sample_format.name(),
info.channel_layout().bits()
);

debug!("audio mixer input {i}: {args}");

filter_graph.add(
&ffmpeg::filter::find("abuffer").expect("Failed to find abuffer filter"),
&format!("src{i}"),
&args,
)
})
.collect::<Result<Vec<_>, _>>()?;
let mut abuffers = Vec::new();
let mut resamplers = Vec::new();

let target_info = AudioMixer::INFO;
let target_rate = target_info.rate();
let target_sample_fmt = target_info.sample_format.name();
let target_channel_layout_bits = target_info.channel_layout().bits();

for (i, source) in self.sources.iter().enumerate() {
let info = &source.info;
let args = format!(
"time_base={}:sample_rate={}:sample_fmt={}:channel_layout=0x{:x}",
info.time_base,
info.rate(),
info.sample_format.name(),
info.channel_layout().bits()
);

debug!("audio mixer input {i}: {args}");

let mut abuffer = filter_graph.add(
&ffmpeg::filter::find("abuffer").expect("Failed to find abuffer filter"),
&format!("src{i}"),
&args,
)?;

let mut resample = filter_graph.add(
&ffmpeg::filter::find("aresample").expect("Failed to find aresample filter"),
&format!("resample{i}"),
&format!(
"out_sample_rate={}:out_sample_fmt={}:out_chlayout=0x{:x}",
target_rate, target_sample_fmt, target_channel_layout_bits
),
)?;

abuffer.link(0, &mut resample, 0);

abuffers.push(abuffer);
resamplers.push(resample);
}

let mut amix = filter_graph.add(
&ffmpeg::filter::find("amix").expect("Failed to find amix filter"),
Expand All @@ -101,12 +118,15 @@ impl AudioMixerBuilder {
),
)?;

let aformat_args = "sample_fmts=flt:sample_rates=48000:channel_layouts=stereo";
let aformat_args = format!(
"sample_fmts={}:sample_rates={}:channel_layouts=0x{:x}",
target_sample_fmt, target_rate, target_channel_layout_bits
);

let mut aformat = filter_graph.add(
&ffmpeg::filter::find("aformat").expect("Failed to find aformat filter"),
"aformat",
aformat_args,
&aformat_args,
)?;

let mut abuffersink = filter_graph.add(
Expand All @@ -115,8 +135,8 @@ impl AudioMixerBuilder {
"",
)?;

for (i, abuffer) in abuffers.iter_mut().enumerate() {
abuffer.link(0, &mut amix, i as u32);
for (i, resample) in resamplers.iter_mut().enumerate() {
resample.link(0, &mut amix, i as u32);
}

amix.link(0, &mut aformat, 0);
Expand All @@ -136,6 +156,7 @@ impl AudioMixerBuilder {
samples_out: 0,
last_tick: None,
abuffers,
resamplers,
abuffersink,
output,
_filter_graph: filter_graph,
Expand Down Expand Up @@ -210,6 +231,7 @@ pub struct AudioMixer {
last_tick: Option<Timestamp>,
// sample_timestamps: VecDeque<(usize, Timestamp)>,
abuffers: Vec<ffmpeg::filter::Context>,
resamplers: Vec<ffmpeg::filter::Context>,
abuffersink: ffmpeg::filter::Context,
_filter_graph: ffmpeg::filter::Graph,
_amix: ffmpeg::filter::Context,
Expand Down
Loading