2010-12-29 16 views
21

मुझे लाइव ऑडियो स्ट्रीम चलाने की ज़रूरत है, वास्तव में यह रेडियो है। समस्या यह है कि मुझे स्ट्रीमिंग के लिए 20 मिनट बफर का प्रबंधन करने की भी आवश्यकता है। जहां तक ​​मैं समझता हूं कि एंड्रॉइड के साथ कार्यान्वित करना आसान नहीं है।ऑडियो स्ट्रीम बफरिंग

सबसे पहले मैंने मीडियाप्लेयर की जांच की, लेकिन यह बफर प्रबंधन के लिए कोई भी तरीका प्रदान नहीं करता है। वास्तव में आप सीधे बफर आकार भी सेट नहीं कर सकते हैं।

दूसरी बार मैंने स्थानीय फाइलों का उपयोग करके बफर का प्रबंधन करने की कोशिश की: प्रगतिशील रूप से स्ट्रीम को अस्थायी फ़ाइलों में डाउनलोड करें और उन्हें स्विच करें। लेकिन जब आप निम्न फ़ाइल पर स्विच करना चाहते हैं (MediaPlayer में डेटास्रोत बदलें), ऑडियो लगातार नहीं खेला जाता है। आप छोटी बाधाओं को सुन सकते हैं।

अंतिम विचार स्ट्रीम प्रॉक्सी का उपयोग करना है। आमतौर पर इसका उपयोग नीचे दिए गए एंड्रॉइड संस्करणों में स्ट्रीम खेलने के लिए किया जाता है। स्ट्रीम प्रॉक्सी में आप सर्वरसॉकेट बनाते हैं, ऑडियो स्ट्रीम से पढ़ते हैं और प्लेयर को लिखते हैं। तो वास्तव में मैं वहाँ बफरिंग का प्रबंधन कर सकते हैं। मैं स्ट्रीम कैश कर सकता हूं और मीडियाप्लेयर को जो कुछ भी चाहता हूं उसे लिख सकता हूं। परंतु। यह एंड्रॉइड 8 के साथ काम नहीं करता है।

मुझे अपवाद मिला: सहकर्मी java.net द्वारा कनेक्शन रीसेट। सॉकेटएक्सप्शन: सहकर्मी द्वारा कनेक्शन रीसेट। MediaPlayer 8 सॉकेट से डेटा नहीं पढ़ना चाहता है।

इस प्रकार मेरे पास दो प्रश्न हैं: 1) स्ट्रीम बफरिंग को लागू करने का दूसरा तरीका क्या है? 2) एंड्रॉइड 8 के लिए StreamProxy को कैसे अनुकूलित करें?

किसी भी विचार की सराहना की जाती है।

धन्यवाद

+0

"2) कैसे एंड्रॉयड 8 के लिए StreamProxy अनुकूल करने के लिए?" ... जब तक आप कोड का उपयोग कर रहे दिखाने के लिए, यह किसी को भी मदद करने के लिए के लिए असंभव है। – Squonk

+1

आप मीडियाप्लेयर को स्ट्रीम कैसे लिख रहे हैं क्या आप थोड़ा और समझा सकते हैं? –

उत्तर

8

मैं एक ही StreamProxy का उपयोग करने वाले लोगों को एनपीआर परियोजना के लिए इस्तेमाल - https://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java

तो यह मूल ऑडियो स्ट्रीम हो जाता है:

String url = request.getRequestLine().getUri(); 
    HttpResponse realResponse = download(url); 
    ... 
    InputStream data = realResponse.getEntity().getContent(); 

और इस धारा से ग्राहक सॉकेट से लिखते हैं:

byte[] buff = new byte[1024 * 50]; 
    while (isRunning && (readBytes = data.read(buff, 0, buff.length)) != -1) { 
    client.getOutputStream().write(buff, 0, readBytes); 
    } 

(आप लिंक से पूरा कोड प्राप्त कर सकते हैं bove)

और अंत में कैसे वे खिलाड़ी (PlaybackService) प्रारंभ:।

if (stream && sdkVersion < 8) { 
    if (proxy == null) { 
     proxy = new StreamProxy(); 
     proxy.init(); 
     proxy.start(); 
    } 
    String proxyUrl = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), url); 
    playUrl = proxyUrl; 
    } 
    ... 
    mediaPlayer.setDataSource(playUrl); 
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 
    mediaPlayer.prepareAsync(); 

तो वे SDK संस्करण की जाँच करें। लेकिन अगर मैं इस चेक को छोड़ देता हूं और एसडीके 8 के लिए प्रॉक्सी का उपयोग करता हूं तो मुझे अपवाद भी मिलता है। यह अजीब है कि MediaPlayer भी धारा पढ़ने की कोशिश नहीं करता है:

12-30 15:09:41.576: DEBUG/StreamProxy(266): downloading... 
12-30 15:09:41.597: DEBUG/StreamProxy(266): reading headers 
12-30 15:09:41.597: DEBUG/StreamProxy(266): headers done 
12-30 15:09:41.647: DEBUG/StreamProxy(266): writing to client 
12-30 15:09:41.857: INFO/AwesomePlayer(34): mConnectingDataSource->connect() returned - 1007 
12-30 15:09:41.857: ERROR/MediaPlayer(266): error (1, -1007) 
12-30 15:09:41.867: ERROR/MediaPlayer(266): Error (1,-1007) 
12-30 15:09:41.867: WARN/AudioService(266): onError(1, -1007) 
12-30 15:09:41.867: WARN/AudioService(266): MediaPlayer refused to play current item. Bailing on prepare. 
12-30 15:09:41.867: WARN/AudioService(266): onComplete() 
12-30 15:09:42.097: ERROR/StreamProxy(266): Connection reset by peer 
     java.net.SocketException: Connection reset by peer 
     at org.apache.harmony.luni.platform.OSNetworkSystem.writeSocketImpl(Native Method) 
     at org.apache.harmony.luni.platform.OSNetworkSystem.write(OSNetworkSystem.java:723) 
     at org.apache.harmony.luni.net.PlainSocketImpl.write(PlainSocketImpl.java:578) 
     at org.apache.harmony.luni.net.SocketOutputStream.write(SocketOutputStream.java:59) 
     at com.skyblue.service.media.StreamProxy.processRequest(StreamProxy.java:204) 
     at com.skyblue.service.media.StreamProxy.run(StreamProxy.java:103) 
     at java.lang.Thread.run(Thread.java:1096) 

ऐसा लगता है कि MediaPlayer अधिक चतुर हो गया। और अगर मैं ऐसे यूआरएल "http://127.0.0.1:%d/%s" पास करता हूं तो यह न केवल बाइट्स बल्कि "पूर्ण" http responce प्राप्त करना चाहता है।

मुझे आश्चर्य है कि क्या बफरिंग लागू करने के अन्य तरीके हैं? जैसा कि मुझे पता है कि मीडियाप्लेयर केवल फाइलों और यूआरएल का उपभोग करता है। फ़ाइलों के साथ समाधान काम नहीं करता है। तो मुझे स्ट्रीम ट्रांसमिटिंग के लिए सॉकेट का उपयोग करना होगा।

धन्यवाद

+2

हाय यूजीनियस, एनपीआर प्रोजेक्ट के पोस्ट किए गए लिंक अब आप एक वैध लिंक पोस्ट कर सकते हैं? –

+0

यहां सही लिंक है: https://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java – stanri

+0

हाय यूजीनियस, क्या आपको मिला मूल समस्या का समाधान? क्या फिक्स आपके लिए ब्रेक काम द्वारा पोस्ट किया गया था? – burakk

2

Mediaplayer एसडीके 8 से एक प्रॉक्सी यूआरएल को पढ़ने में सक्षम नहीं होगा। लेकिन मेरे वर्तमान काम के आधार पर, यह डिवाइस से डिवाइस में भिन्न है। मेरे सैमसंग एसीई (एसडीके 8) में प्रॉक्सी कनेक्शन ठीक काम करता है, लेकिन मेरे एचटीसी इनक्रेडिबल एस में, प्रॉक्सी कनेक्शन आपके जैसा ही मुद्दा देगा।ऑडियो स्ट्रीम का सीधा कनेक्शन ठीक काम करता है लेकिन इससे स्प्रिंट पर ईवीओ जैसे कुछ उपकरणों में ब्लिप और बूप्स का कारण बनता है।

क्या आपको इस मुद्दे के लिए कोई समाधान मिला? आपने इसे कैसे संभाला?

-Hari

+0

मैंने एक ही व्यवहार का अनुभव किया है, और मुझे 99% यकीन है कि यह अंतर्निहित मीडिया प्लेयर से जुड़ा हुआ है। वर्तमान मीडिया प्लेयर (AwesomePlayer/StageFright) का उपयोग करने वाले अधिकांश एसडीके 8 डिवाइस पर, 'कनेक्शन रीसेट' होगा। हालांकि, कुछ डिवाइस पुराने मीडिया प्लेयर (पीवीप्लेयर) का उपयोग करते हैं, और कोई त्रुटि नहीं होगी। – brack

5

मैं सिर्फ निम्नलिखित ठीक परीक्षण किया है, और यह काम करता है। यह समस्या "\ n"StreamProxy की विधि में शीर्षलेखों में उपयोग की जाती है। इसे पर बदलना "\ r \ n" त्रुटि को दूर करना चाहिए।

कस्टम स्ट्रीमिंग को लागू करने के लिए, मैंने इसे अतीत में उपयोग किया है, हालांकि यह मुख्य रूप से असीमित स्ट्रीमिंग रेडियो के लिए प्रतीत होता है। http://blog.pocketjourney.com/2009/12/27/android-streaming-mediaplayer-tutorial-updated-to-v1-5-cupcake/

+0

ब्लॉग पोस्ट यूआरएल exsist नहीं है। – Murat

3

जब आप खोजते हैं या छोड़ते हैं या कनेक्शन खो जाता है और मीडियाप्लेयर प्रॉक्सी सर्वर से दोबारा जुड़ता रहता है, तो आपको ग्राहक से अनुरोध और सीमा (int) प्राप्त करने के बाद स्थिति 206 के साथ यह प्रतिक्रिया भेजनी होगी।

String headers += "HTTP/1.1 206 Partial Content\r\n"; 
headers += "Content-Type: audio/mpeg\r\n"; 
headers += "Accept-Ranges: bytes\r\n"; 
headers += "Content-Length: " + (fileSize-range) + "\r\n"; 
headers += "Content-Range: bytes "+range + "-" + fileSize + "/*\r\n"; 
headers += "\r\n"; 

और जब आप कि HTTP शीर्ष लेख में रेंज शामिल नहीं है MediaPlayer से एक अनुरोध प्राप्त करते हैं, तो यह एक नई धारा फ़ाइल अनुरोध कर रहा है, इस मामले में अपनी प्रतिक्रिया हेडर कुछ इस तरह दिखना चाहिए:

String headers = "HTTP/1.1 200 OK\r\n"; 
headers += "Content-Type: audio/mpeg\r\n"; 
headers += "Accept-Ranges: bytes\r\n"; 
headers += "Content-Length: " + fileSize + "\r\n"; 
headers += "\r\n"; 

आनंद लें!

1

मुझे एहसास है कि यह प्रश्न 5 साल की तरह है, लेकिन अगर कोई और घूम रहा है: एक्सोप्लेयर Google से लाइब्रेरी है जो आपको बफर आकार जैसे विकल्पों पर अधिक नियंत्रण देता है।

//DefaultUriDataSource – For playing media that can be either local or loaded over the network. 
    DefaultUriDataSource dataSource = new DefaultUriDataSource(WgtechApplication.getAppContext(), 
      Util.getUserAgent(WgtechApplication.getAppContext(), WgtechApplication.class.getSimpleName())); 
    Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE); 

    //ExtractorSampleSource – For formats such as MP3, M4A, MP4, WebM, MPEG-TS and AAC. 
    ExtractorSampleSource sampleSource = new ExtractorSampleSource(Uri.parse(RADIO_STREAMING_URL), 
      dataSource, allocator, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE); 
    player.prepare(new MediaCodecAudioTrackRenderer(sampleSource)); 

यहां एक छोटी परियोजना है जिसे मैंने इसका उपयोग करने के तरीके के बारे में जानने के लिए बनाया है। https://github.com/feresr/MyMediaPlayer

http://developer.android.com/guide/topics/media/exoplayer.html https://github.com/google/ExoPlayer

संबंधित मुद्दे