这可能不是一个可以接受的问题,但我现在非常绝望。
我需要一个同步java媒体播放器与快速寻找和平衡修改。
脚本:
我有一个javaFX项目,我必须在循环中播放一个非常短(50-100毫秒)的媒体文件。问题是,在重新启动之前,我需要等待一些要求。
简而言之:播放声音-
javafx提供了一个我修改过的媒体播放器。
// this method is just to show how the modified mediaplayer class is called
public void updateSoundBalance(double currentTimeInCycle) {
// control the balance of the sound
if(playingSound && mediaPlayer != null)
{
long b = System.nanoTime();
// 0 <= balance < 4. balance represents the cycle phase.
double balance = currentTimeInCycle % RADIANCE_FULL_CYCLE / RADIANCE_QUARTER_CYCLE;
boolean firstHalfCycle = balance < 2;
double quarterCycleIndex = Math.floor(balance);
long a = System.nanoTime();
if(swingingSound)
mediaPlayer.setBalance(firstHalfCycle ? 1 - balance : balance - 3);
else
mediaPlayer.setBalance(balance > 1 && balance < 3? -1 : 1);
System.out.println("C ::: sound balance = " + (System.nanoTime() - a));
if ((quarterCycleIndex == 1 | quarterCycleIndex == 3) &&
balance - quarterCycleIndex <= Settings.DEFAULT_PATTERN_SMOOTHNESS)
{
a = System.nanoTime();
if (mediaDone){
mediaPlayer.reset();
mediaDone = false;
}
System.out.println("B ::: call reset = " + (System.nanoTime() - a));
}
System.out.println("A ::: total time = " + (System.nanoTime() - b));
}
}
import java.util.concurrent.ScheduledThreadPoolExecutor;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.util.Duration;
public class MultiMediaPlayer
{
private MediaPlayer mp1, mp2;
private boolean usingMp1 = true;
private ScheduledThreadPoolExecutor seekService = new ScheduledThreadPoolExecutor(2);
private Runnable seekRun = new Runnable() {
@Override
public void run() {
try
{
long a = System.nanoTime();
if(usingMp1) {
usingMp1 = false;
mp1.stop();
mp2.play();
mp1.seek(new Duration(0));
} else {
usingMp1 = true;
mp2.stop();
mp1.play();
mp2.seek(new Duration(0));
}
System.out.println("D ::: reset sound time taken = " + (System.nanoTime() - a));
}
catch (Exception e){
e.printStackTrace();
}
}
};
public MultiMediaPlayer(Media value)
{
mp1 = new MediaPlayer(value);
mp2 = new MediaPlayer(value);
mp1.balanceProperty().bindBidirectional(mp2.balanceProperty());
mp1.onEndOfMediaProperty().bindBidirectional(mp2.onEndOfMediaProperty());
}
public void setBalance(double value){
mp1.setBalance(value);
}
public void reset(){
seekService.execute(seekRun);
}
public void play(){
if(usingMp1) {
mp1.play();
} else {
mp2.play();
}
}
public void stop(){
mp1.stop();
mp2.stop();
}
public void pause(){
mp1.pause();
mp2.pause();
}
public void setOnEndOfMedia(Runnable r) {
mp1.setOnEndOfMedia(r);
}
}
如果有人能为我指出正确的方向(图书馆/我错过的东西),我将不胜感激
ps允许的java版本是最新的
谢谢Olof Kohlhaas,但我想我找到了一个更好的解决方案,它使用了javafx的音频剪辑。然而,由于我缺乏知识,我使用了一种基本的方法来获取文件的长度,它只支持Wave和其他特定格式。如果更改了,该类将使用javafx媒体包支持的任何格式:
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.media.AudioClip;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
/**
*
* this class is to optimize sound pattern playing
*
* reasoning:
* - audio clips are for short repetitive files that don't need live changes to balance
* - media players are for long files that will have the ability to swing with the visual patted
* by updating the balance whenever needed (every few updates)
*/
public class AudioPlayer
{
public enum Controller{
MEDIA_PLAYER, AUDIO_CLIP;
}
/**
* this class is to help other classes keep track of this particular state of the AudioPlayer
*/
public class ControllerProperty extends SimpleObjectProperty<Controller>{
SimpleBooleanProperty isMediaPlayerProperty = new SimpleBooleanProperty();
@Override
public void set(Controller newValue) {
super.set(newValue);
if (newValue == Controller.MEDIA_PLAYER)
isMediaPlayerProperty.set(true);
else
isMediaPlayerProperty.set(false);
}
public ReadOnlyBooleanProperty isMediaPlayerProperty() {
return isMediaPlayerProperty;
}
}
// different controllers used
private Media media;
private MediaPlayer mediaPlayer;
private AudioClip audioClip;
// controllerProperty property indicator
private ControllerProperty controllerProperty = new ControllerProperty();
private boolean mediaDonePlaying = true;
private double durationMillis;
/**
* Constructor. This will be the place where you can
* @param srcUrl
*/
public AudioPlayer(String srcUrl) {
boolean formatSupported = true;
try {
durationMillis = getLength(srcUrl);
} catch (IOException | LineUnavailableException e) {
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
formatSupported = false;
}
// if file is long or format unsupported (not one of these: AudioSystem.getAudioFileTypes())
if (durationMillis > 400 | !formatSupported){
media = new Media(srcUrl);
mediaPlayer = new MediaPlayer(media);
controllerProperty.set(Controller.MEDIA_PLAYER);
mediaPlayer.setOnEndOfMedia(() -> mediaDonePlaying = true);
}
else {
audioClip = new AudioClip(srcUrl);
controllerProperty.set(Controller.AUDIO_CLIP);
}
}
/**
* gets the audio duration of the provided source in milliseconds
* @param path url string representation of the path
* @return the length in milliseconds
* @throws IOException
* @throws UnsupportedAudioFileException
* @throws LineUnavailableException
*/
public static double getLength(String path) throws IOException, UnsupportedAudioFileException, LineUnavailableException
{
AudioInputStream stream;
stream = AudioSystem.getAudioInputStream(new URL(path));
AudioFormat format = stream.getFormat();
if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format
.getSampleRate(), format.getSampleSizeInBits() * 2, format
.getChannels(), format.getFrameSize() * 2, format
.getFrameRate(), true); // big endian
stream = AudioSystem.getAudioInputStream(format, stream);
}
DataLine.Info info = new DataLine.Info(Clip.class, stream.getFormat(),
((int) stream.getFrameLength() * format.getFrameSize()));
Clip clip = (Clip) AudioSystem.getLine(info);
clip.close();
return clip.getBufferSize()
/ (clip.getFormat().getFrameSize() * clip.getFormat()
.getFrameRate());
}
public void stop(){
switch (controllerProperty.get())
{
case AUDIO_CLIP:
if (audioClip != null)
audioClip.stop();
break;
case MEDIA_PLAYER:
if (mediaPlayer != null && media != null){
mediaPlayer.stop();
mediaDonePlaying = true;
}
break;
}
}
public void play(){
switch (controllerProperty.get())
{
case AUDIO_CLIP:
if (audioClip != null)
if(!audioClip.isPlaying()){
audioClip.play();
}
break;
case MEDIA_PLAYER:
if (mediaPlayer != null && media != null){
mediaPlayer.play();
mediaDonePlaying = false;
}
break;
}
}
public void pause(){
switch (controllerProperty.get())
{
case AUDIO_CLIP:
if (audioClip != null)
audioClip.stop();
break;
case MEDIA_PLAYER:
if (mediaPlayer != null && media != null)
mediaPlayer.pause();
break;
}
}
/**
* sets the balance of the player, if the controller is an {@link AudioClip}, the balance is
* updated at the next play cycle, if the controller is a {@link MediaPlayer} the balance is
* updated at the next time the {@link MediaPlayer} has Status.READY (read
* {@link MediaPlayer#setBalance(double)} for more details)
* @param balance
*/
public void setBalance(double balance){
switch (controllerProperty.get())
{
case AUDIO_CLIP:
if (audioClip != null)
audioClip.setBalance(balance);
break;
case MEDIA_PLAYER:
if (mediaPlayer != null && media != null)
mediaPlayer.setBalance(balance);
break;
}
}
public String getSource(){
switch (controllerProperty.get())
{
case AUDIO_CLIP:
if (audioClip != null)
return audioClip.getSource();
break;
case MEDIA_PLAYER:
if (mediaPlayer != null && media != null)
return media.getSource();
break;
}
return null;
}
/**
* @return if the file is done
*/
public boolean isDonePlaying(){
switch (controllerProperty.get())
{
case AUDIO_CLIP:
if (audioClip != null)
return !audioClip.isPlaying();
break;
case MEDIA_PLAYER:
if (mediaPlayer != null && media != null)
return mediaDonePlaying;
break;
}
throw new IllegalStateException("Internal Error");
}
public ControllerProperty controllerProperty() {
return controllerProperty;
}
}
在这种情况下,您最好使用更低级的Java声音API。它已经是标准API的一部分。你提到你有很短的音频信号。因此,您可以将其缓冲在内存中,然后将其写入大纲多次。乍一看您的代码,pan似乎是正确的选择,而不是平衡。下面的示例演示如何将天平和平移分别切换到其最大值和最小值。Java Sound API与WAVE和AIFF本机协同工作。如果您有其他文件格式,则需要查看Java声音API FormatConversionProviders,例如mp3spi和vorbisspi。
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Main {
public static void main(String[] args) {
try {
int loops = 20;
File waveFile = new File(yourWaveFilePath);
AudioInputStream stream = AudioSystem.getAudioInputStream(waveFile);
AudioFormat format = stream.getFormat();
// reading complete audio file into memory
byte[] frames = new byte[format.getFrameSize() * (int) stream.getFrameLength()];
stream.read(frames, 0, frames.length);
DataLine.Info lineInfo = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(lineInfo);
line.open(format);
line.start();
FloatControl balance = (FloatControl) line.getControl(FloatControl.Type.BALANCE);
FloatControl pan = (FloatControl) line.getControl(FloatControl.Type.PAN);
for (int i = 0; i < loops; i++) {
// switching balance and pan with every iteration
if (i % 2 == 0) {
balance.setValue(balance.getMinimum());
pan.setValue(pan.getMinimum());
} else {
balance.setValue(balance.getMaximum());
pan.setValue(pan.getMaximum());
}
// playing complete audio file
line.write(frames, 0, frames.length);
System.out.println("iteration: " + i + ", balance: " + balance.getValue() + ", pan: " + pan.getValue());
}
line.drain();
line.close();
stream.close();
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}
}
}
大家好,我正在尝试使用两个独立的媒体播放器实例播放音频和视频文件。当我从一开始播放它时,它工作得很好。但当我寻找时,我可以看到音频和视频的延迟 这是我寻找音频和视频的代码 //sikAudio(msec); if(media播放器!=null) { // 没有直播流,如果(medialayer.get持续时间() }
我正在开发一个包含一些音频播放器的RecyclerView的应用程序。应用程序将下载。3gp文件(如果尚未下载)。 当我单击playAudio按钮时,音频未被播放。 这是我的适配器代码: 我怎样才能解决这个问题?
1.1.1. 多媒体播放 1.1.1. 多媒体播放 我们事实上对上游芯片厂商自带的播放器方式做了调整。 Amlogic 芯片 BaseCode 我们禁用了芯片厂商的原生代码的 libplayer 包,原因是芯片厂商的播放器是直接使用 ALSA 框架来调用音频播放功能的。 这对我们 RokidOS 平台让多个进程使用音频设备造成阻碍。基于这个因素,我们使用了 RokidOS 开发的媒体播放库 lib
当我使用MediaPlayer播放mp3文件时,系统会报告错误日志:。但是RealPlayer是正常的。 我发现它的错误只发生在更高的ROM版本。像4.0版本一样,它有错误。在2.3版中,它没有这个错误。 代码: 日志猫错误:
我已经成功地能够从我的服务器流MP3,现在我想显示一个媒体播放器通知与控制时,歌曲开始播放。我已经遵循了一些教程如何做到这一点,但我仍然得到错误时,试图在我的应用程序中做同样的事情。 这是我尝试在音乐开始播放时显示通知的方式 这是完整的 但是,当我运行代码并单击播放按钮时,应用程序崩溃,logcat返回此错误,但没有指向特定的代码行。
我目前在一个项目中使用Javafx 2,我可能需要长时间无限循环播放一个视频。在windows上,当视频播放时,我的proifiler工具显示非常正常的图片,cpu负载不是很重(在2个内核上运行时约为2x40-50%),内存使用峰值约为250 MB,这是正常的。但是,当我在Ubuntu机器上部署应用程序时,每个内核的cpu负载达到70%左右(尽管它是一个双核atom处理器,所以假设这是正常的),内