I'm using vlcj in java to playback wav files, that are being expanded by other services. My problem is the following:
when I open an audio file the player knows that the duration is x sec. If it reaches the end it has to reopen (player.controls().start()) the file to know the expanded duration. This restart causes a micro stutter in playback (like 0.1 second) but it can be heard, and if the expanding process is slow than the stuttering can happen like every 2 seconds.
I have no way to modify the underlying architecture, so i can not use streaming.
The main issue as I see after hours of research is that vlcj do not provide a way to manually update the duration (that i can calculate by the file size) of the played audio file (it probably loads it to memory on open i guess).
Does somebody tried to implement this kind of playback with success?
After extended research in the topic I concluded that stutterless playback with the above described setup cannot be achieved. It can be optimized greatly, but will never be perfect. The root of the problem is that the length (duration) of the played wav file cannot be set manually, thus reload is a must for rescan.
My solution for this was to implement a live555 RTSP streaming server between the storage and the client. The vlcj player connects to the rtsp stream and plays the (expanding) file seamlessly. The drawbacks are that the playtime needs specific handling, and has less performance (slower response to events).
Related
Is there a good recipe to get decent, reliable digital sampled sound playback in Java?
My list of requests is pretty short:
Load digitized samples in memory (for example, from resouces bundled in jar) from something like .wav files
Play them in non-blocking manner
When I play several samples simultaneously and they intersect in time, they should get properly mixed
It would be nice to have the following, but in fact I can live without it:
Playing from .ogg or similar compressed format (without implementing a CPU-hungry decoder in Java, obviously)
Playing back the same sample again while it is still playing should not stop previous playback of a given sample, but second copy should start and get properly mixed with the first one
I've tried the infamous Java Sound API, but found out that it is utterly unreliable and seem to be unable to satisfy even my minimal wish list. The problems I get:
On Linux with ALSA dmix (OpenJDK 6), having any other application using audio while initializing Java Sound API just makes all the sound from Java app disappear without any errors / warnings.
On Linux (OpenJDK 6), listing MixerInfos and trying to get a Clip object using any of them throws the following exception when trying to load a wav file:
java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian
Thus, AudioSystem.getClip(anySortOfMixer) doesn't seem to work at all. Only AudioSystem.getClip() works.
Loading files with different sample rate / bits / format using Clip fails with LineUnavailableException. It seems that first invocation of clip.open sets up sound system to a particular sound options, following invocations to load a file with slightly different sample rate (for example, first one was 44100, second one is 48000)
On Linux (OpenJDK 6) initializing several different Clips and trying to play them makes only last loaded Clip audible - no errors/warnings are given, but only using play on last Clip loaded makes any sound at all - all others are silent:
Clip loadSound(String name) {
URL url = this.getClass().getResource("/" + name + ".wav");
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
clip.open(ais);
return clip;
}
void playSound(Clip) {
if (clip.isRunning())
clip.stop();
clip.setFramePosition(0);
clip.start();
}
...
Clip c1 = loadSound("foo");
Clip c2 = loadSound("bar");
...
playSound(c1); // silence
...
playSound(c2); // audible
Everything's fine with this code on Windows - all Clips are audible, play and mix properly. Haven't tested it on Mac.
Supported file formats (analyzed with AudioSystem.getAudioFileTypes) returns wav / au / aif on both Linux/OpenJDK6 and Windows/Oracle JDK 7, so no oggs or even mp3s :(
There seem to be no easy way to make two copies of the same Clip sound simultaneously without loading 2nd copy as a distinct Clip.
So, the question is - is there a good solution / workaround to remedy all this stuff and make it more reliable? Would switching to some other sound system (such as LWJGL OpenAL or paulscode.com sound system) help? Or is it possible to wrap Java Sound API in some safe-guards and it will work properly?
I've made a little application that tests all of the above, but it's a bit long, so I thought I'd publish it as a gist, but, unfortunately, GitHub is having some network issues right now. So, I guess, I will publish it a bit later.
I posted a fairly simple, limited, audio mixer at Java-gaming.org, which you are welcome to check out at the following url:
http://www.java-gaming.org/topics/simple-audio-mixer-2nd-pass/27943/view.html
The jar listed in the first post has source code and sample usages and I put some energy into making javadoc comments. (98% of the download is the single sample wav I included.) Also, on the thread is a lot of api info.
It has issues with Linux, still. But I am impressed with your analysis, and am wondering about sharing in the effort to try and troubleshoot and fix this!
On your points:
I recall hearing that with some Linux systems, a single output is all that is possible, and that some applications do not play fair and release the audio to Java when there is contention. To the extent that this is accurate, it would be hard to call this a Java problem, but rather perhaps a Linux OS problem?
Second point: I haven't tried loading from a Mixer in Linux yet, but I know some folks have been able to do this from my web app Java Theremin. In that app (linked in the above thread) I include a dropdown that allows the user to choose the mixer. At least some of the Linux users have had success with this.
I haven't used Big-Endian wavs -- but only little endian wavs. You'd have to flip the bytes in Audacity or something similar to use my mixer as it currently stands.
My system DOES handle concurrency. You load a wav into a PFClipData object. Then, you can play this back a number of different ways, via a PFClipShooter (can handle concurrent playbacks--20 or 30, and at different pitches as well) or a PFClipLooper (will loop the clip with optional overlap modes of the end to help smooth out the looping point). ALL output is funneled into a single SourceDataLine behind the scenes.
I haven't implemented ogg or mp3 yet, just 16-bit, 44100fps stereo little-endian wav files.
Would be happy to consider making this an open source git project, if there were others willing to share in this.
--I succeeded in installing Linux (Ubuntu Desktop) in a dual boot partition on my PC very recently, and am about to install a sound card and see if I recreate and hopefully fix some of the problems that are being described. The Ubuntu has both OpenJDK and Oracle's JDK, so I hope to see if the Java implementation might be part of the issue. Work in progress...
How does one obtain the system sound, (beeps and such), and then record it and output to a sound file? I can get sound from a line - in mic, but I can't figure out how to get the actual system sound.
Any assistance?
This has been a long unanswered question which has been frustrating me as well.
I found a way to capture/record Windows' audio output, but it is more of a hack job rather then an actual solution. Disclaimer: This is my blog. I say this because from what I have found Java doesn't capture the data from a specified audio device [See the official Accessing Audio System Resources Java tutorial (although you can list out all of the audio I/O devices/audio ports, See: Programming JavaSound), instead it just takes the default device (which is how I 'solved' the problem).
This, however, introduces a problem where because the default recording device is no longer the microphone, you can no longer record from the microphone as another input; Although, using the Port.Info class to capture the microphone might be a possible solution to this side effect.
I hope this will help.
I'm writing an accompaniment application that continuously needs to play specific notes (or even chords). I have a thread running that figures out which note I need to play, but I have no idea where to begin regarding the actual playback. I know I can create an audiotrack and write a sine wave to it, but for this project a simple tone won't cut it. So I'm guessing I either need to use MIDI (can android do that?) or to somehow take a sample and change its pitch on the fly, but I don't know if that's even possible.
All I can say is to check out pitch-shifting (which you seem to have heard of) and soundpool (which would require some recording of your own) and these 2 links:
Audio Playback Rate in Android
Programmatically increase the pitch of an array of audio samples
the second link seems to have more info.
I installed Red5 1.0 on EC2 running linux. My goal is to record webcam video from my website -- connect to a user's webcam and save the video to S3.
I tried out the video recorder application in the pre-installed demo apps. It works, but when I play back the recorded flv video, the quality is terrible.
At best, the video is extremely pixelated and blurs with motion
At worst, the video doesn't even play -- it just stays stuck on one frame
Most often, the video and audio are totally out of sync and choppy. I found that I could affect this be increasing the buffer allowance on the server using one of the config files, but increasing the buffer seems to cause the video to get choppy.
I've tried connecting with multiple computers and even a fast corporate internet connection. Interestingly, the quality issues persist even when connecting to localhost, so it doesn't seem to be a network problem.
When I use the red5-recorder.com flash app to record to the demo server app, the quality is even worse.
Ultimately, I just want to get a high quality video recording from a visitor's webcam, but don't want to drop the money for FMS or Wowza.
Any ideas on how to get Red5 to record high quality? Is it always this bad?
Thanks for your help!!
The quality of recorded video is not related with RED5 settings but your flash app settings. Just try to set Camera.setQuality() to something more suitable to your needs. For example if you use setQuality(0, 100) you'll get the best possible video quality but bandwidth use also increase.
We experience the same problem with 0.91 version. I read somewhere that 0.8 was fine. You might try that one..
Try using Red5 RC1 it will surely give you much better recording but i am also trying to find something even better and i have not come up with something till now..if you solved your problem i would be glad to hear a better approach..
All Red5 versions (up to and including 1.0.2 ) have been plagued by serious video recording issues. See this answer for a list of all versions and their issues.
Red5 1.0.3 is the 1st version of Red5 with the video recording process fixed because it's the 1st to contain this awesome patch.
Quick explanation of the 2 part cause
Flash Player buffering (only) video packets
Flash Player is known to buffer video packets and send only audio packets when the network conditions do not allow it to send both.
This works very well for live video scenarios where you want to keep at least the audio going but NOT for video recording scenarios where the locally buffered video packets end up arriving too late at the media server (the corresponding .flv section might have already been written to disk).
That's why AMS and Wowza have implemented delayed write mechanism where they wait for the video packets to arrive before writing the data to disk.
Red5's bug
Red5 also had such a mechanism but, due to a serious bug, it was dropping the video packets instead waiting for them.
The bug fas fixed with the patch mentioned above.
How much Red5 will wait for buffered video packets is controlled by fileconsumer.queue.size in conf/red5.properties. it defaults to 120 which should be enough for a buffer of 2 minutes of HD video.
Further reading
delayed.write and queue.size mechanism flawed? on the Red5 mailing list
Recording high quality (HD) video over slow connections with Red5 is now possible
I have a list of radio stations, mostly .mp3 and .ogg. I would like to have a player on a web page that could be controlled with JavaScript. Now I use jlgui, but it is somewhat limited.
Do you know of any alternative to jlgui? Preferably a java applet, but I can tolerate flash or even a system-default media player for a particular content-type.
There are a thousand MP3 players for Flash, using the native streaming stuff. Unfortunately that copes generally poorly with streamed MP3 (either over Icecast HTTP, or even more so under SHOUTcast ICY). Generally the player has to reconnect to the stream every so often, causing a playback glitch, otherwise memory just fills with MP3 data.
OGG is harder. There's no native support, but in Flash 10 you can play any old samples you can decode yourself, so it's possible to implement your own OGG decoder. It needs a lot of CPU on the client though. See http://barelyfocused.net/blog/2008/10/03/flash-vorbis-player/ — I don't know of anyone having fixed this up into a single player that can do both MP3 and OGG from the same interface yet, but there's no reason it shouldn't be possible.
I found JPlayer which uses HTML5 if available, otherwise it falls back to Flash. Works almost as good as the JLgui
You can use the JMF I guess:
link
JMF Applet