Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient way to seek a streaming audio over network with InputStream

I'm playing an audio file using jlGui's BasicPlayer (it's based on Javasound). The file is in a Samba share and I'm using Jcifs to access it. It gives me an InputStream.

NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication( ... );

SmbFile f = new SmbFile( ... );
SmbFileInputStream audioIn = new SmbFileInputStream(f);

int bufSize = 8096;//should I use f.length() here?
audioBIS = new BufferedInputStream(audioIn, bufSize);

audioBIS.mark(f.length());

    //call BasicPlayer
play(audioBIS);

I need to be able to position the pointer anywhere in the file, just like any common player. The only solution I could think of was to use a BufferedInputStream and a combination of mark/reset/skip everytime I need to reposition the pointer. As soon as I open the file and get the Stream, I call the mark() method, so that a subsequent reset() will reposition me at the beginning. Then with skip() I can go where I want.

audioBIS.reset();
audioBIS.skip(newBytePosition);

My problem is that the skip() call works as desired only if I specify a buffer big enough to contain the whole file.

Is there a more efficient way to do this?

like image 970
Giuseppe Avatar asked Jul 27 '12 10:07

Giuseppe


1 Answers

I've been down the excact same path as you are now. The case was that we had a server (and a SMB share) holding thousands of audio files. These files needed to be playable in an application.

I started out with jCifs, and modified the source of BasicPlayer to deal with SmbFile the same way it would deal with File. It worked alright, but when it comes to seeking/skipping it does not really blow you away. As long as you've got a good connection to the server, you should be alright.

I ended up ditching that solution, and instead installed tomcat6 on the server and deployed a small and simple servlet that would allow requests to be made for a file at a given position. The client machine would then take the response as an InputStream and pass that on to BasicPlayer. It works much better, and the playback is instant. The code is a little more than what is reasonable to paste here, but I'd be willing to share it with you if you are interested.

like image 150
sbrattla Avatar answered Oct 12 '22 23:10

sbrattla