我正在尝试使用javaCV在命令行中读取来自ffmpeg的音频RTP流。我创建了一个侦听指定端口但无法获取音频帧的DatagramSocket。
我尝试使用不同类型的缓冲区将音频播放到扬声器,但是我收到很多“流协议的无效返回值0”错误消息,扬声器中没有音频。
我正在运行以下命令以流式传输音频文件:
ffmpeg -re -i /some/file.wav -ar 44100 -f mulaw -f rtp rtp://127.0.0.1:7780
到目前为止,我的代码节选:
公共类FrameGrabber实现了Runnable {
private static final TimeUnit SECONDS = TimeUnit.SECONDS;
private InetAddress ipAddress;
private DatagramSocket serverSocket;
public FrameGrabber(Integer port) throws UnknownHostException, SocketException {
super();
this.ipAddress = InetAddress.getByName("192.168.44.18");
serverSocket = new DatagramSocket(port, ipAddress);
}
public AudioFormat getAudioFormat() {
float sampleRate = 44100.0F;
// 8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
// 8,16
int channels = 1;
// 1,2
boolean signed = true;
// true,false
boolean bigEndian = false;
// true,false
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
@Override
public void run() {
byte[] buffer = new byte[2048];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(packet.getData(), packet.getOffset(), packet.getLength()));
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(dis);
grabber.setFormat("mulaw");
grabber.setSampleRate((int) getAudioFormat().getSampleRate());
grabber.setAudioChannels(getAudioFormat().getChannels());
SourceDataLine soundLine = null;
try {
grabber.start();
if (grabber.getSampleRate() > 0 && grabber.getAudioChannels() > 0) {
AudioFormat audioFormat = new AudioFormat(grabber.getSampleRate(), 16, grabber.getAudioChannels(), true, true);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
soundLine = (SourceDataLine) AudioSystem.getLine(info);
soundLine.open(audioFormat);
soundLine.start();
}
ExecutorService executor = Executors.newSingleThreadExecutor();
while (true) {
try {
serverSocket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
Frame frame = grabber.grab();
//if (frame == null) break;
if (frame != null && frame.samples != null) {
ShortBuffer channelSamplesFloatBuffer = (ShortBuffer) frame.samples[0];
channelSamplesFloatBuffer.rewind();
ByteBuffer outBuffer = ByteBuffer.allocate(channelSamplesFloatBuffer.capacity() * 2);
float[] samples = new float[channelSamplesFloatBuffer.capacity()];
for (int i = 0; i < channelSamplesFloatBuffer.capacity(); i++) {
short val = channelSamplesFloatBuffer.get(i);
outBuffer.putShort(val);
}
if (soundLine == null) return;
try {
SourceDataLine finalSoundLine = soundLine;
executor.submit(() -> {
finalSoundLine.write(outBuffer.array(), 0, outBuffer.capacity());
outBuffer.clear();
}).get();
} catch (InterruptedException interruptedException) {
Thread.currentThread().interrupt();
}
}
}
/*
executor.shutdownNow();
executor.awaitTermination(1, SECONDS);
if (soundLine != null) {
soundLine.stop();
}
grabber.stop();
grabber.release();*/
} catch (ExecutionException ex) {
System.out.println("ExecutionException");
ex.printStackTrace();
} catch (org.bytedeco.javacv.FrameGrabber.Exception ex) {
System.out.println("FrameGrabberException");
ex.printStackTrace();
} catch (LineUnavailableException ex) {
System.out.println("LineUnavailableException");
ex.printStackTrace();
}/* catch (InterruptedException e) {
System.out.println("InterruptedException");
e.printStackTrace();
}*/
}
public static void main(String[] args) throws SocketException, UnknownHostException {
Runnable apRunnable = new FrameGrabber(7780);
Thread ap = new Thread(apRunnable);
ap.start();
}
}
在这个阶段,我正在尝试在扬声器中播放音频文件,但是我收到以下日志:
任务:FrameGrabber.main() 流协议的无效返回值0 流协议的无效返回值0 从'java.io.DataInputStream@474e6cea'输入#0,mulaw: 持续时间:不适用,比特率:352 kb / s 流#0:0:音频:pcm_mulaw,44100 Hz,1个通道,s16、352 kb / s 流协议的无效返回值0 流协议的无效返回值0 流协议的无效返回值0 流协议的无效返回值0 ...
我在做什么错了?
谢谢!