Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Exoplayer播放器视频mp4 e流m3u8_Java_Android_Video_Exoplayer - Fatal编程技术网

Java Exoplayer播放器视频mp4 e流m3u8

Java Exoplayer播放器视频mp4 e流m3u8,java,android,video,exoplayer,Java,Android,Video,Exoplayer,有没有办法让exoplayer同时运行mp4和m3u8流视频 我试过了,但找不到解决办法 我找到了以下测试来源 视频mp4: 流m3u8: 这是我在mp4视频作品中编写的代码,但在m3u8中,没有 我做了几次尝试,但没有成功,我正在考虑使用HlsMediaSource,但我无法使它工作 错误,在SimpleVideoStream.java中调用了以下函数: public void onPlayerError(ExoPlaybackException error) { 代码: AndroidM

有没有办法让exoplayer同时运行mp4和m3u8流视频

我试过了,但找不到解决办法

我找到了以下测试来源

视频mp4:

流m3u8:

这是我在mp4视频作品中编写的代码,但在m3u8中,没有

我做了几次尝试,但没有成功,我正在考虑使用HlsMediaSource,但我无法使它工作


错误,在
SimpleVideoStream.java
中调用了以下函数:

public void onPlayerError(ExoPlaybackException error) {
代码:

AndroidManifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ui.exoplayer">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".SimpleVideoStream"
            android:configChanges="orientation|screenSize"
            android:screenOrientation="landscape" />
    </application>

</manifest>
SimpleVideoStream:

package com.ui.exoplayer;

import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.WindowManager;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MergingMediaSource;
import com.google.android.exoplayer2.source.SingleSampleMediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;

public class SimpleVideoStream extends AppCompatActivity implements ExoPlayer.EventListener {
    public static final int PERMISSIONS_REQUEST_CODE = 0;

    SimpleExoPlayerView playerView;
    SimpleExoPlayer player;
    DataSource.Factory dataSourceFactory;
    MediaSource videoSource;

    String url, sub;
    Boolean showTitle = true, showSub = false;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Bundle b = getIntent().getExtras();
        url = b.getString("url", "");
        sub = b.getString("sub", "");

        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        playerView = (SimpleExoPlayerView) findViewById(R.id.exo_player_view);

        // 1. Create a default TrackSelector
        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

        // 2. Create a default LoadControl
        LoadControl loadControl = new DefaultLoadControl();

        // 3. Create the player
        player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
        playerView.setPlayer(player);
        playerView.setKeepScreenOn(true);
        playerView.setRewindIncrementMs(5 * 1000);
        playerView.setFastForwardIncrementMs(5 * 1000);

        // Produces DataSource instances through which media data is loaded.
        dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayer"));

        // Produces Extractor instances for parsing the media data.
        final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

        // This is the MediaSource representing the media to be played.
        videoSource = new ExtractorMediaSource(Uri.parse(url), dataSourceFactory, extractorsFactory, null, null);

        // Prepare the player with the source.
        player.addListener(this);
        player.prepare(videoSource);
        playerView.requestFocus();
        player.setPlayWhenReady(true);// to play video when ready. Use false to pause a video

        if (!sub.equals("") && b.getBoolean("subShow")) addSub(sub);
    }


    @Override
    protected void onPause() {
        super.onPause();
        if (player != null) {
            player.setPlayWhenReady(false); //to pause a video because now our video player is not in focus
        }
    }

    @Override
    public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
    }

    @Override
    public void onLoadingChanged(boolean isLoading) {
    }

    @Override
    public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
        switch (playbackState) {
            case ExoPlayer.STATE_BUFFERING:
                //You can use progress dialog to show user that video is preparing or buffering so please wait
                break;
            case ExoPlayer.STATE_IDLE:
                //idle state
                break;
            case ExoPlayer.STATE_READY:
                // dismiss your dialog here because our video is ready to play now
                break;
            case ExoPlayer.STATE_ENDED:
                // do your processing after ending of video
                break;
        }
    }

    @Override
    public void onPlayerError(ExoPlaybackException error) {
        // show user that something went wrong. I am showing dialog but you can use your way
        AlertDialog.Builder adb = new AlertDialog.Builder(this);
        adb.setTitle("Could not able to stream video");
        adb.setMessage("It seems that something is going wrong.\nPlease try again.");
        adb.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                finish(); // take out user from this activity. you can skip this
            }
        });
        AlertDialog ad = adb.create();
        ad.show();
    }


    @Override
    public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
    }

    @Override
    public void onRepeatModeChanged(int repeatMode) {
    }

    @Override
    public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
    }

    @Override
    public void onPositionDiscontinuity(int reason) {
    }

    @Override
    public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
    }

    @Override
    public void onSeekProcessed() {
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

    private void removeSub() {
        showSub = false;
        final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
        videoSource = new ExtractorMediaSource(Uri.parse(url), dataSourceFactory, extractorsFactory, null, null);
        player.prepare(videoSource, false, false);
    }

    private void addSub(String sub) {
        removeSub();
        showSub = true;
        Format textFormat = Format.createTextSampleFormat(null, MimeTypes.APPLICATION_SUBRIP, null, Format.NO_VALUE, Format.NO_VALUE, "en", null, Format.OFFSET_SAMPLE_RELATIVE);
        MediaSource textMediaSource = new SingleSampleMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(sub), textFormat, C.TIME_UNSET);
        videoSource = new MergingMediaSource(videoSource, textMediaSource);
        player.prepare(videoSource, false, false);
    }

}

我相信您确实需要使用HlsMediaSource来传输HLS(m3u8)。以下示例适用于DASH、HLS和mp4

// 1. Create a default TrackSelector
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new 
    AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new 
    DefaultTrackSelector(videoTrackSelectionFactory);

playerView = rootView.findViewById(R.id.videoView);
player = ExoPlayerFactory.newSimpleInstance(<context>, trackSelector);
player.setPlayWhenReady(true);
playerView.setPlayer(player);

// DASH
//    DefaultHttpDataSourceFactory dataSourceFactory = new DefaultHttpDataSourceFactory(
//        Util.getUserAgent(<context>, "ExoPlayer"));
//    DefaultDashChunkSource.Factory chunkSourceFactory = new 
//        DefaultDashChunkSource.Factory(dataSourceFactory);
//
//    MediaSource mediaSource = new DashMediaSource(Uri.parse(<dash url>), 
//        dataSourceFactory, chunkSourceFactory, null, null);


// HLS
//    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(<context>,
//        Util.getUserAgent(rootView.getContext(), "ExoPlayer"));
//
//    // Produces Extractor instances for parsing the media data.
//    ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
//    Handler mainHandler = new Handler();
//    MediaSource mediaSource = new HlsMediaSource(Uri.parse(
//    "https://live3-mediaset-it.akamaized.net/content/hls_clr_xo/live/channel(ch09)/Stream(02)/index.m3u8"),
//        dataSourceFactory, null, null);

// MP4
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(<context>,
    Util.getUserAgent(rootView.getContext(), "ExoPlayer"));

// Produces Extractor instances for parsing the media data.
final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

// This is the MediaSource representing the media to be played.
MediaSource mediaSource = new ExtractorMediaSource(Uri.parse(
    "https://www.w3schools.com/html/mov_bbb.mp4"),
    dataSourceFactory, extractorsFactory, null, null);

player.prepare(mediaSource);
player.setPlayWhenReady(true);
//1。创建默认轨迹选择器
带宽计带宽计=新的默认带宽计();
TrackSelection.Factory videoTrackSelectionFactory=新建
自适应跟踪选择。工厂(带宽计);
TrackSelector TrackSelector=新建
默认轨迹选择器(videoTrackSelectionFactory);
playerView=rootView.findviewbyd(R.id.videoView);
player=ExoPlayerFactory.newImpleInstance(,trackSelector);
player.setplaywhenrady(true);
playerView.setPlayer(player);
//冲刺
//DefaultHttpDataSourceFactory dataSourceFactory=新的DefaultHttpDataSourceFactory(
//getUserAgent(,“ExoPlayer”);
//DefaultDashChunkSource.Factory chunkSourceFactory=新建
//DefaultDashChunkSource.Factory(dataSourceFactory);
//
//MediaSource MediaSource=新的DashMediaSource(Uri.parse(),
//dataSourceFactory,chunkSourceFactory,null,null);
//HLS
//DataSource.Factory dataSourceFactory=新的DefaultDataSourceFactory(,
//getUserAgent(rootView.getContext(),“ExoPlayer”);
//
////生成用于解析媒体数据的提取器实例。
//提取器工厂提取器工厂=新的默认提取器工厂();
//Handler mainHandler=新处理程序();
//MediaSource MediaSource=新的HlsMediaSource(Uri.parse(
//    "https://live3-mediaset-it.akamaized.net/content/hls_clr_xo/live/channel(ch09)/流(02)/索引m3u8“,
//dataSourceFactory,null,null);
//MP4
//生成加载媒体数据的数据源实例。
DataSource.Factory dataSourceFactory=新的DefaultDataSourceFactory(,
getUserAgent(rootView.getContext(),“ExoPlayer”);
//生成用于解析媒体数据的提取器实例。
最终提取器工厂提取器工厂=新的默认提取器工厂();
//这是表示要播放的媒体的媒体源。
MediaSource MediaSource=new extractoremiasource(Uri.parse(
"https://www.w3schools.com/html/mov_bbb.mp4"),
数据源工厂,提取器工厂,null,null);
player.prepare(mediaSource);
player.setplaywhenrady(true);

这将是一个用Kotlin编写的更优雅的解决方案,用于处理
.mp4
以及
.m3u8
流式URL

示例
layout.xml

    <com.google.android.exoplayer2.ui.PlayerView
        android:id="@+id/videoPlayerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
下面的方法处理
mp4
m3u8
流媒体的播放

    private fun buildMediaSource(uri: Uri): MediaSource {
        val userAgent = Util.getUserAgent(videoPlayerView.context, getString(R.string.app_name))
        val lastPathSegment = uri.lastPathSegment
        return if (lastPathSegment?.contains("mp3") == true ||
            lastPathSegment?.contains("mp4") == true
        ) {
            ProgressiveMediaSource.Factory(DefaultHttpDataSourceFactory(userAgent))
                .createMediaSource(uri)
        } else if (lastPathSegment?.contains("m3u8") == true) {
            HlsMediaSource.Factory(DefaultHttpDataSourceFactory(userAgent))
                .createMediaSource(uri)
        } else {
            val dashChunkSourceFactory = DefaultDashChunkSource.Factory(
                DefaultHttpDataSourceFactory("ua", null)
            )
            val manifestDataSourceFactory = DefaultHttpDataSourceFactory(userAgent)
            DashMediaSource.Factory(dashChunkSourceFactory, manifestDataSourceFactory)
                .createMediaSource(uri)
        }
    }


请发布一篇文章,并添加运行/编译代码时出现的问题。@Michail:我认为对于那些了解Exoplayer的人来说,这篇文章已经非常详尽了,但是我列出了启动它所需的一切。如果你填的时候少了什么,请告诉我。我希望你现在知道怎么帮我了?破折号到底是什么意思?HLS类型仅适用于m3u8?在您为HLS发布的示例中,您具体在哪里使用mainHandler?您可以为我做一个测试,因为我发布的代码没有成功。如果您阅读HLS,您可以试试吗?因为如您所示,已修改了该文件,所以读取m3u8但不起作用。DASH用于流mpd文件。与HLS类似,只是协议不同。实际上没有使用mainHandler。ExtractOrmDiaSource构造函数的可选参数。如果我取消上面HLS部分的注释,并注释掉MP4块,我就能够流式处理您的示例m3u8文件。如果这不适用于您,您可以发布您看到的错误消息吗?错误,在SimpleVideoStream.java中调用以下函数:public void onPlayerError(ExoPlaybackException错误){很抱歉,我无法提供足够的信息来帮助您。如果您记录ExoPlaybackException错误的内容,您可能会学到一些东西。有点困惑,但当我理解您的意思时,它对我来说很好,流式播放HSL-m3u播放列表
        var exoPlayer: ExoPlayer? = null
        exoPlayer = SimpleExoPlayer.Builder(videoPlayerView.context).build()
        exoPlayer?.repeatMode = Player.REPEAT_MODE_OFF
        videoPlayerView.player = exoPlayer
        val uri: Uri = Uri.parse(url)
        val mediaSource = buildMediaSource(uri)
        exoPlayer?.prepare(mediaSource, true, false)
        exoPlayer?.playWhenReady = true

    private fun buildMediaSource(uri: Uri): MediaSource {
        val userAgent = Util.getUserAgent(videoPlayerView.context, getString(R.string.app_name))
        val lastPathSegment = uri.lastPathSegment
        return if (lastPathSegment?.contains("mp3") == true ||
            lastPathSegment?.contains("mp4") == true
        ) {
            ProgressiveMediaSource.Factory(DefaultHttpDataSourceFactory(userAgent))
                .createMediaSource(uri)
        } else if (lastPathSegment?.contains("m3u8") == true) {
            HlsMediaSource.Factory(DefaultHttpDataSourceFactory(userAgent))
                .createMediaSource(uri)
        } else {
            val dashChunkSourceFactory = DefaultDashChunkSource.Factory(
                DefaultHttpDataSourceFactory("ua", null)
            )
            val manifestDataSourceFactory = DefaultHttpDataSourceFactory(userAgent)
            DashMediaSource.Factory(dashChunkSourceFactory, manifestDataSourceFactory)
                .createMediaSource(uri)
        }
    }