2011-11-25 618 views
23

我想直播視頻,並且它採用m3u8格式。所以,我想下面的代碼在Android中播放m3u8視頻

public class StreamingPlayer extends Activity implements 
OnBufferingUpdateListener, OnCompletionListener, 
OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback{ 

    private static final String TAG = StreamingPlayer.class.getSimpleName(); 
    private int mVideoWidth; 
    private int mVideoHeight; 
    private MediaPlayer mMediaPlayer; 
    private SurfaceView mPreview; 
    private SurfaceHolder holder; 
    private String path; 

    private boolean mIsVideoSizeKnown = false; 
    private boolean mIsVideoReadyToBePlayed = false; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.mediaplayer_2); 
     mPreview = (SurfaceView) findViewById(R.id.surface); 
     holder = mPreview.getHolder(); 
     holder.addCallback(this); 
     holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    private void playVideo() { 
     doCleanUp(); 
     try { 

      /* 
      * TODO: Set path variable to progressive streamable mp4 or 
      * 3gpp format URL. Http protocol should be used. 
      * Mediaplayer can only play "progressive streamable 
      * contents" which basically means: 1. the movie atom has to 
      * precede all the media data atoms. 2. The clip has to be 
      * reasonably interleaved. 
      * 
      */ 

      path = "httplive://xboodangx.api.channel.livestream.com/3.0/playlist.m3u8"; 

      if (path == "") { 
       // Tell the user to provide a media file URL. 
       Toast 
       .makeText(
         this, 
         "Please edit MediaPlayerDemo_Video Activity," 
         + " and set the path variable to your media file URL.", 
         Toast.LENGTH_LONG).show(); 
      } 

      Log.e("PATH", "Path = " + path); 
      // Create a new media player and set the listeners 
      mMediaPlayer = new MediaPlayer(); 
      mMediaPlayer.setDataSource(path); 
      mMediaPlayer.setDisplay(holder); 
        mMediaPlayer.setOnBufferingUpdateListener(this); 
        mMediaPlayer.setOnPreparedListener(this); 
      mMediaPlayer.prepare(); 
      mMediaPlayer.setOnCompletionListener(this); 
      mMediaPlayer.setOnVideoSizeChangedListener(this); 
      mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 

     } catch (Exception e) { 
      Log.e(TAG, "error: " + e.getMessage(), e); 
     } 
    } 

    public void onBufferingUpdate(MediaPlayer arg0, int percent) { 
     Log.d(TAG, "onBufferingUpdate percent:" + percent); 

    } 

    public void onCompletion(MediaPlayer arg0) { 
     Log.d(TAG, "onCompletion called"); 
    } 

    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 
     Log.v(TAG, "onVideoSizeChanged called"); 
     if (width == 0 || height == 0) { 
      Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")"); 
      return; 
     } 
     mIsVideoSizeKnown = true; 
     mVideoWidth = width; 
     mVideoHeight = height; 
     if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { 
      startVideoPlayback(); 
     } 
    } 

    public void onPrepared(MediaPlayer mediaplayer) { 
     Log.d(TAG, "onPrepared called"); 
     mIsVideoReadyToBePlayed = true; 
     if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { 
      startVideoPlayback(); 
     } 
    } 

    public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) { 
     Log.d(TAG, "surfaceChanged called"); 

    } 

    public void surfaceDestroyed(SurfaceHolder surfaceholder) { 
     Log.d(TAG, "surfaceDestroyed called"); 
    } 


    public void surfaceCreated(SurfaceHolder holder) { 
     Log.d(TAG, "surfaceCreated called"); 
     playVideo(); 

    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     releaseMediaPlayer(); 
     doCleanUp(); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     releaseMediaPlayer(); 
     doCleanUp(); 
    } 

    private void releaseMediaPlayer() { 
     if (mMediaPlayer != null) { 
      mMediaPlayer.release(); 
      mMediaPlayer = null; 
     } 
    } 

    private void doCleanUp() { 
     mVideoWidth = 0; 
     mVideoHeight = 0; 
     mIsVideoReadyToBePlayed = false; 
     mIsVideoSizeKnown = false; 
    } 

    private void startVideoPlayback() { 
     Log.v(TAG, "startVideoPlayback"); 
     holder.setFixedSize(mVideoWidth, mVideoHeight); 
     mMediaPlayer.start(); 
    } 


} 

在logcat的它顯示onBufferingUpdate percent:100但我不能看視頻。

音頻正在工作,但突然它被擊中。

而我試過這個視頻鏈接http://devimages.apple.com/iphone/samples/bipbop/gear1/prog_index.m3u8它工作。但我的視頻鏈接不工作,我改變了httplive://... instead of http://但沒用。我看到這個答案Android video stream mms and m3u8

在上面的鏈接顯示視頻無法播放的消息。

+0

您是否試過在真實設備上進行測試?有時模擬器在處理HTTP直播流時很糟糕。 – yorkw

+0

@yorkw感謝您的回覆。是我在真實設備中測試過,而不是仿真器。 – Ramakrishna

+0

URI h t t p://myvideo.m3u8對我來說很奇怪,你在哪裏主持媒體?遠程服務器?如果您可以訪問服務器端的廣播代碼,請嘗試將其更改爲更加穩定的URL,例如hdo t://domain-name/service-name/myvideo.m3u8。不知道這項工作,但值得去嘗試。 – yorkw

回答

14

該視頻存在於http://www.livestream.com。在這裏有移動API進行直播。

所述API是:

http://www.livestream.com/userguide/index.php?title=Mobile_API#How_to_get_mobile_compatible_clips_from_a_channel.27s_library

在上述鏈路存在用於移動設備兼容的全部信息。爲了得到rtsp鏈接從通道使用這個鏈接

http://xproshowcasex.channel-api.livestream-api.com/2.0/getstream

替換,而不是proshowcase的頻道名稱。然後獲取所有移動兼容的網址,如iPhone,Android,Blackberry等。

使用該網址,您可以使用視頻視圖或媒體播放器在Android中流式傳輸視頻。

欲瞭解更多信息,請閱讀手機API鏈接。

如果有人得到相同的問題,我希望這個答案會幫助你。

祝你好運。

+0

可以看到代碼工作嗎?面臨同樣的問題 –

+0

@GuillermoVarini上述代碼不適用於我。請閱讀我的答案,並詳細告訴我你的問題,然後我會告訴你答案,如果我知道。 – Ramakrishna

+0

問題是我需要在2.1應用程序上播放一個m3u8視頻,我無法找到如何做到這一點的真實例子。在這裏找到2個帖子,但沒有工作。也檢查了developer.android.com/但沒有:你說這個API有用嗎?有如何實現的例子? –

1

,我認爲你應該將這樣的:

mMediaPlayer.setOnPreparedListener(this); 

要調用prepare()

+0

謝謝你的迴應。我實現了你的想法,但它不工作。直到它顯示onBufferingUpdate百分比:100,我不能看到視頻 – Ramakrishna

1

你有沒有嘗試直接通過網絡瀏覽器來播放用本地播放器的鏈接之前? 如果您無法使用本機播放,則表示您的文件不受當前Android版本的支持。 HTTP Live Streaming格式可以具有某些Android不能很好支持的特性,但它可以在IOS上播放。

+0

感謝您的response.It工作它的android本地播放器和IOS也。有已經完成了這項任務。 – Ramakrishna

0

我試過m3u8視頻格式超過6個月,並沒有成功。它在我的iPhone應用程序和本地應用程序中播放。我的流媒體服務器是Red5,它沒有RTSP插件。它給出了RTMP流媒體,並且無法在Android中進行流式傳輸。我等了一年纔得到支持RTSP流媒體的操作系統,但谷歌沒有。儘管如此,我仍然使用網絡視圖和Flash播放器來傳輸實況視頻(它沒有太多的清晰度)。我很遺憾地對我的客戶說這些,並繼續搜索以在Android默認播放器中播放實時流。

我認爲你的視頻網址可能不是RTSP。

4

我沒有問題,打流:

videoView1.setVideoPath("http://***.net/livedemo/_definst_/stream3.stream/playlist.m3u8?wowzasessionid=773395207"); 
videoView1.start(); 

有關消息:

視頻無法播放

也許你需要的權限添加到您的清單文件:

<uses-permission android:name="android.permission.INTERNET"/> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 
+3

沒有必要。 – Jorgesys

+0

同樣的問題。你找到解決方案嗎? –

+0

Sergey

0

如何在Android的

activity_main.xml中發揮.M3U8流

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" > 

    <VideoView 
     android:id="@+id/myVideoView" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" /> 
</LinearLayout> 

Main.java

package com.grexample.ooyalalive; 

import java.net.URL; 
import android.app.Activity; 
import android.net.Uri; 
import android.os.Bundle; 
import android.widget.MediaController; 
import android.widget.VideoView; 

public class Main extends Activity { 

    private String urlStream; 
    private VideoView myVideoView; 
    private URL url; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main_vv);//*************** 
      myVideoView = (VideoView)this.findViewById(R.id.myVideoView); 
      MediaController mc = new MediaController(this); 
      myVideoView.setMediaController(mc);   
      urlStream = "http://jorgesys.net/i/[email protected]/master.m3u8"; 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        myVideoView.setVideoURI(Uri.parse(urlStream)); 
       } 
      }); 
    } 
} 

我已經看到了很多人播放.M3U8時出現問題,這取決於用於流式傳輸的編解碼器a nd與設備的兼容性,例如,某些.m3u8文件僅在屏幕爲1200 x800或更高的設備中受支持。

+3

你不需要在onCreate中調用runOnUiThread,你已經UI線程 – busylee