java 实时播放android采集的音频,android - 在Android中使用Audiotrack播放javacv-ffmpeg解码的音频 - 堆栈内存溢出...

这个Java示例展示了如何利用FFmpegFrameGrabber捕获视频流,并通过FloatBuffer提取音频,同时利用JavaFX展示视频和播放音频。程序首先初始化FFmpegFrameGrabber,设置音频格式,然后在独立线程中处理视频帧和音频样本,将视频帧转化为FXImage显示,将音频样本转换为适合播放的数据并写入SourceDataLine进行播放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

您可以使用FFmpegFrameGrabber类捕获流。 并使用FloatBuffer类提取音频。 这是一个java示例

public class PlayVideoAndAudio extends Application

{

private static final Logger LOG = Logger.getLogger(JavaFxPlayVideoAndAudio.class.getName());

private static final double SC16 = (double) 0x7FFF + 0.4999999999999999;

private static volatile Thread playThread;

public static void main(String[] args)

{

launch(args);

}

@Override

public void start(Stage primaryStage) throws Exception

{

String source = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov";

StackPane root = new StackPane();

ImageView imageView = new ImageView();

root.getChildren().add(imageView);

imageView.fitWidthProperty().bind(primaryStage.widthProperty());

imageView.fitHeightProperty().bind(primaryStage.heightProperty());

Scene scene = new Scene(root, 640, 480);

primaryStage.setTitle("Video + audio");

primaryStage.setScene(scene);

primaryStage.show();

playThread = new Thread(() -> {

try {

FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(source);

grabber.start();

primaryStage.setWidth(grabber.getImageWidth());

primaryStage.setHeight(grabber.getImageHeight());

AudioFormat audioFormat = new AudioFormat(grabber.getSampleRate(), 16, grabber.getAudioChannels(), true, true);

DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);

SourceDataLine soundLine = (SourceDataLine) AudioSystem.getLine(info);

soundLine.open(audioFormat);

soundLine.start();

Java2DFrameConverter converter = new Java2DFrameConverter();

ExecutorService executor = Executors.newSingleThreadExecutor();

while (!Thread.interrupted()) {

Frame frame = grabber.grab();

if (frame == null) {

break;

}

if (frame.image != null) {

Image image = SwingFXUtils.toFXImage(converter.convert(frame), null);

Platform.runLater(() -> {

imageView.setImage(image);

});

} else if (frame.samples != null) {

FloatBuffer channelSamplesFloatBuffer = (FloatBuffer) frame.samples[0];

channelSamplesFloatBuffer.rewind();

ByteBuffer outBuffer = ByteBuffer.allocate(channelSamplesFloatBuffer.capacity() * 2);

for (int i = 0; i < channelSamplesFloatBuffer.capacity(); i++) {

short val = (short)((double) channelSamplesFloatBuffer.get(i) * SC16);

outBuffer.putShort(val);

}

/**

* We need this because soundLine.write ignores

* interruptions during writing.

*/

try {

executor.submit(() -> {

soundLine.write(outBuffer.array(), 0, outBuffer.capacity());

outBuffer.clear();

}).get();

} catch (InterruptedException interruptedException) {

Thread.currentThread().interrupt();

}

}

}

executor.shutdownNow();

executor.awaitTermination(10, TimeUnit.SECONDS);

soundLine.stop();

grabber.stop();

grabber.release();

Platform.exit();

} catch (Exception exception) {

LOG.log(Level.SEVERE, null, exception);

System.exit(1);

}

});

playThread.start();

}

@Override

public void stop() throws Exception

{

playThread.interrupt();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值