1 year ago
#179336

Chris
Trying to record computer audio (not Microphone)
I'm playing around with javax.sound
libraries for the first time and I'm trying to record audio that is currently playing through my computer's default device, such as music or a video (not a microphone).
I might just be getting myself confused between TargetDataLine
and SourceDataLine
, but no matter what I try, all I can manage to do is record sound from the microphone.
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
@Slf4j
@Service
public class AudioServiceImpl implements AudioService {
private final File wavFile = new File("output.wav");
private final AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
private TargetDataLine line;
@Override
public void start() {
final Mixer defaultMixer = getMixersWithAudioFormats().stream()
.filter(mixer -> mixer.getMixerInfo().getName().equals("Default Audio Device"))
.findFirst()
.orElseThrow(() -> new RuntimeException("No default audio device found"));
try {
final AudioInterface audioInterface = getAudioFormat(defaultMixer);
line = (TargetDataLine) AudioSystem.getLine(audioInterface.info());
line.open(line.getFormat());
line.start();
AudioInputStream audioInputStream = new AudioInputStream(line);
log.info("Recording...");
AudioSystem.write(audioInputStream, fileType, wavFile);
} catch (LineUnavailableException | IOException ex) {
ex.printStackTrace();
}
}
/**
* Find the first audio format where the line is supported.
*/
private AudioInterface getAudioFormat(final Mixer mixer) {
for (final Line.Info mixerInfo : mixer.getTargetLineInfo()) {
final AudioFormat[] formats = getFormats(mixerInfo);
for (final AudioFormat format : formats) {
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if (AudioSystem.isLineSupported(info)) {
return new AudioInterface(format, info);
}
}
}
throw new RuntimeException("No supported audio format found");
}
/**
* Find all mixers with audio formats.
*/
private List<Mixer> getMixersWithAudioFormats() {
final List<Mixer> results = new LinkedList<>();
for (Mixer.Info info : AudioSystem.getMixerInfo()) {
final Mixer mixer = AudioSystem.getMixer(info);
final Line.Info[] lineInfos = mixer.getTargetLineInfo();
for (Line.Info lineInfo : lineInfos) {
if ((lineInfo instanceof final DataLine.Info dataLineInfo) && (dataLineInfo.getFormats().length > 0)) {
results.add(mixer);
}
}
}
return results;
}
/**
* Helper to grab audio formats from a line info.
*/
private AudioFormat[] getFormats(final Line.Info lineInfo) {
return lineInfo instanceof final DataLine.Info dataLineInfo ? dataLineInfo.getFormats() : null;
}
@PreDestroy
void finish() {
line.stop();
line.close();
}
}
The AudioInterface
is just a helper record
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.DataLine;
public record AudioInterface(AudioFormat format, DataLine.Info info) {
}
My understanding is that I'm correctly grabbing the Default Audio Device mixer, extracting the format out of it and loading that into the AudioSystem.getLine
method. I just would have thought that to end up recording from the microphone I'd have to have been using a different mixer (In my case, MacBook Pro Microphone) instead.
Where have I gone wrong here?
java
javasound
0 Answers
Your Answer