精华内容
下载资源
问答
  • ExoPlayer使用GLSurfaceView,opengles来播放视频。
  • ExoPlayer 使用备份

    2021-05-05 21:31:27
    ExoPlayer

    简介

    ExoPlayer 是一个不在 Android 框架内的开放源代码项目,它与 Android SDK 分开提供。ExoPlayer 的标准音频和视频组件基于 Android 的 MediaCodec API 构建,该 API 是在 Android 4.1(API 级别 16)中发布的。由于 ExoPlayer 是一个库,因此您可以通过更新应用来轻松利用新推出的功能。

    ExoPlayer 支持基于 HTTP 的动态自适应流 (DASH)、SmoothStreaming 和通用加密等功能,这些功能不受 MediaPlayer 的支持。它采用易于自定义和扩展的设计。

    https://github.com/google/ExoPlayer

    简单使用

    添加依赖

    1,添加完整版依赖

        //此为写文章时的最新版
        def exo_version = "2.13.3"
        implementation "com.google.android.exoplayer:exoplayer:$exo_version"

    2,按需添加依赖

        def exo_version = "2.13.3"
        //基础库
        implementation "com.google.android.exoplayer:exoplayer-core:$exo_version"
        //默认UI库
        implementation "com.google.android.exoplayer:exoplayer-ui:$exo_version"
        //dash库
        implementation "com.google.android.exoplayer:exoplayer-dash:$exo_version"
        //hls库
        implementation "com.google.android.exoplayer:exoplayer-hls:$exo_version"
        //smoothstreaming
        implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:$exo_version"
        //OKHttp扩展
        implementation "com.google.android.exoplayer:extension-okhttp:$exo_version"

    更多的扩展库可以在这里查询:https://github.com/google/ExoPlayer/tree/release-v2/extensions

    添加StyledPlayerView

    添加ui库

        //默认UI库
        implementation "com.google.android.exoplayer:exoplayer-ui:$exo_version"

    添加StyledPlayerView

    StyledPlayerView playerView=new StyledPlayerView(this);

    添加SimpleExoPlayer

                BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder(this.getApplicationContext()).build();
                DefaultTrackSelector trackSelector = new DefaultTrackSelector(this);
                trackSelector.setParameters(trackSelector.buildUponParameters().setMaxVideoSizeSd());
                SimpleExoPlayer player = new SimpleExoPlayer.Builder(this)
                        .setTrackSelector(trackSelector)
                        .setBandwidthMeter(bandwidthMeter)
                        .setUseLazyPreparation(true)
                        .setHandleAudioBecomingNoisy(true)
                        .setWakeMode(C.WAKE_MODE_LOCAL)
                        .setHandleAudioBecomingNoisy(true)
                        .build();
                player.addAnalyticsListener(new EventLogger(trackSelector));
                playerView.setPlayer(player);
    

    创建DataSource.Factory

    这里我使用okhttp扩展,方便监听,设置dns,处理加密等等。

        //OKHttp扩展
        implementation "com.google.android.exoplayer:extension-okhttp:$exo_version"
            //设置默认请求头
            Map<String, String> header = new HashMap<>();
            header.put("allowCrossProtocolRedirects", "true");
            header.put("Referer", referer);
            header.put("Origin",origin);
    
            OkHttpClient client = APP.getCachetClient(APP.getCache("exoplayercache", 1024 * 1024 * 500));
            DataSource.Factory dataSourceFactory = new OkHttpDataSource.
                    Factory(client)
                    .setUserAgent(HttpTool.UA)
                    .setDefaultRequestProperties(header);

    创建MediaSource

    对于hls内容,可使用HlsMediaSource,需要hls扩展。

        //hls库
        implementation "com.google.android.exoplayer:exoplayer-hls:$exo_version"

     

    HlsMediaSource hlsMediaSource =
                            new HlsMediaSource.Factory(dataSourceFactory)
                             .setAllowChunklessPreparation(true)//优化hls加载速度
                             .createMediaSource(MediaItem.fromUri(url));//hls视频的url
    player.addMediaSource(hlsMediaSource);

    对于普通内容,使用ProgressiveMediaSource。

    ProgressiveMediaSource progressiveMediaSource =
                            new ProgressiveMediaSource.Factory(dataSourceFactory)
                                    .createMediaSource(MediaItem.fromUri(url));
    player.addMediaSource(progressiveMediaSource);

    对于dash视频,使用DashMediaSource,需要dash扩展。

        //dash库
        implementation "com.google.android.exoplayer:exoplayer-dash:$exo_version"

     

    MediaSource dashMediaSource =
        new DashMediaSource.Factory(dataSourceFactory)
            .createMediaSource(MediaItem.fromUri(dashUri));
    player.addMediaSource(dashMediaSource);

    对于SmoothStreaming视频,使用SsMediaSource,需要使用SmoothStreaming扩展。

        //smoothstreaming
        implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:$exo_version"

     

    MediaSource ssMediaSource =
        new SsMediaSource.Factory(dataSourceFactory)
            .createMediaSource(MediaItem.fromUri(ssUri));
    player.addMediaSource(ssMediaSource);

    开始播放

    player.prepare();
    player.setPlayWhenReady(true);

    添加字幕

    exoplayer 支持srt,vtt,ass/ssa等格式的字幕,只支持简单的样式。

        DataSource.Factory assetsdataSourceFactory;
    
        public MediaSource buildSubTitleSources(String path, String mimetype, String language) {
            if (assetsdataSourceFactory == null) {
                DataSource.Factory assetsdataSourceFactory = new DefaultDataSourceFactory(this, "");
                Uri srtfileass = Uri.parse(path);
    
                MediaItem.Subtitle subtitle = new MediaItem.Subtitle(
                        srtfileass, mimetype, language, C.SELECTION_FLAG_DEFAULT);
    
                return new SingleSampleMediaSource.Factory(assetsdataSourceFactory).createMediaSource(subtitle, C.TIME_UNSET);
            } else {
                DataSource.Factory assetsdataSourceFactory = new DefaultDataSourceFactory(this, "");
                Uri srtfileass = Uri.parse(path);
    
                MediaItem.Subtitle subtitle = new MediaItem.Subtitle(
                        srtfileass, mimetype, language, C.SELECTION_FLAG_AUTOSELECT);
    
                return new SingleSampleMediaSource.Factory(assetsdataSourceFactory).createMediaSource(subtitle, C.TIME_UNSET);
            }
    
    
        }
    
            MediaSource ass = buildSubTitleSources("file:///android_asset/test.ass", MimeTypes.TEXT_SSA, "ASS");
            MediaSource vtt = buildSubTitleSources("file:///android_asset/test.vtt", MimeTypes.TEXT_VTT, "VTT");
            MediaSource srt = buildSubTitleSources("file:///android_asset/test.srt", MimeTypes.APPLICATION_SUBRIP, "SRT");
            //videoMediasource为视频Mediasource
            MergingMediaSource mergedSource = new MergingMediaSource(videoMediasource,ass, vtt, srt);
           player.addMediaSource(mergedSource)

    在播放界面显示字幕切换

    playerView.setShowSubtitleButton(true);//显示切换字幕界面

    添加视频标题

    ExoPlayer没有设置标题的方法,但可以通过自定义View的方法来实现显示标题的功能。

                LinearLayout.LayoutParams lp1=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
                lp1.leftMargin=dp2px(5);
                lp1.topMargin=dp2px(5);
                lp1.gravity= Gravity.CENTER_VERTICAL;
                LinearLayout ll=new LinearLayout(this);
                ll.setLayoutParams(lp0);
                ll.setBackgroundColor(getResources().getColor(R.color.exo_black_opacity_60));
                TextView textView=new TextView(this);
                textView.setLayoutParams(lp1);
                textView.setMaxLines(1);
                textView.setSingleLine();
                //textView.setBackgroundColor(Color.BLACK);
                textView.setTextColor(Color.WHITE);
                textView.setText(video.video_name);
                ll.addView(textView);
                int len = playerView.getChildCount();
                for (int i = 0; i < len; i++) {
                    View view = playerView.getChildAt(i);
                    if (view != null && view.getClass().getName().equals(StyledPlayerControlView.class.getName())) {
                        StyledPlayerControlView cv= (StyledPlayerControlView) view;
                        cv.addView(ll);
    
                    }
    
                }

     

    全屏按钮

                //全屏按钮调用
                playerView.setControllerOnFullScreenModeChangedListener(new StyledPlayerControlView.OnFullScreenModeChangedListener() {
                    @Override
                    public void onFullScreenModeChanged(boolean isFullScreen) {
                        if (isFullScreen) {
                            requestFull(true);//全屏
                        } else {
                            requestFull(false);//退出全屏
                        }
                    }
                });

     

     

     

     

     

     

     

     

    展开全文
  • Exoplayer使用记录3-网络播放相关的一些事

    Exoplayer使用记录3-网络播放相关的一些事

    By Xdestiny. 2018/2/5

    概述

    网络播放本来其实没啥好说的,毕竟ExoPlayer都已经封装的很完善了。但毕竟有时候还需要一些特殊功能,例如缓存功能、限制下载速度,等等。

    缓存功能

    对于在线播放来说,缓存可以说不可或缺的。那么在ExoPlayer中要怎么做呢?先翻翻文档好了。果然,有一个SimpleCache是可以使用的。那么,大体上来说,缓存功能可以这么做
    - 首先搞一个用于下载、删除缓存的接口。利用SimpleCache将视频存储在本地的某一个位置
    - 读取URL的时候,同样声明一个SimpleCache到同样的路径。这样Exoplayer内部会匹配URL与缓存文件。如果之前有缓存,那么就能够直接使用缓存

    下载速度限制

    有了缓存功能,那么就又来了个新问题…缓存的时候总不好把人带宽占满吧?那么就需要限制下下载速度
    老样子,先上Issue上搜搜有啥思路没。搜一下立刻发现已经有人问过了
    Is there a method to limit the downloading bandwidth
    里面也给了个思路,大致是对DataSource进行一些限制。其实,在缓存的时候,必然会启动一个线程进行下载的操作,那么可以在这个时候线程进行一段时间,然后暂停一段时间。

    具体代码

    class MyCache(activity: Activity, uri: String, isExternalCache: Boolean = true)
        : CacheDataSource.EventListener
    {
        private val TAG = "MyCache"
        private val MAX_BYTE_SIZE: Long = 4L*1024*1024*1024
        private val m_context = activity
        private val m_isExternalCache = isExternalCache
        private val m_uri = uri
        private val simpleCache = SimpleCache(File(if(m_isExternalCache) m_context.externalCacheDir else m_context.cacheDir, "media_cache"), NoOpCacheEvictor())
        private val cacheDataSourceFactory = CacheDataSourceFactory(simpleCache, DefaultDataSourceFactory(m_context, Util.getUserAgent(m_context, "ExoPlayerBridge"), DefaultBandwidthMeter()),
                FileDataSourceFactory(), CacheDataSinkFactory(simpleCache, Long.MAX_VALUE), 0, this)
        var IsCaching = false
            private set(value) {field = value}
            get() = field
        var LimitSpeedRatio: Float = 0.0f
        var CacheByte: Long = Math.max(0, simpleCache.getCachedBytes(m_uri, 0, MAX_BYTE_SIZE))
            get() = field
            private set(value) { field = value }
        var ContentByte: Long = -1
            get() = simpleCache.getContentLength(m_uri)
        var CachedSpace: Long = 0
            get() = simpleCache.cacheSpace
        private var th : Thread? = null
    
        init{
    
        }
    
        fun PreCache(){
            //缓存功能
            if(!m_uri.startsWith("http") || IsCaching) return
            Log.d(TAG, "Start cache. Uri = $m_uri")
            LimitSpeedRatio = 0.0f //限速比例
            th = thread(true){
                IsCaching = true
                val dataSpec = DataSpec(Uri.parse(m_uri))
                val dataSource = cacheDataSourceFactory.createDataSource()
                try{
                    dataSource.open(dataSpec)
                    val scratchSpace = ByteArray(32 * 1024)
                    var bytesRead = 0
                    CacheByte = 0
                    var miliSec = 0L
                    while (bytesRead != C.RESULT_END_OF_INPUT && IsCaching) {
                        val lastMiliSec = System.currentTimeMillis()
                        CacheByte += bytesRead
                        bytesRead = dataSource.read(scratchSpace, 0, scratchSpace.size)
                        miliSec += System.currentTimeMillis() - lastMiliSec
                        if(miliSec > 100 && LimitSpeedRatio > 0.01){
                            Thread.sleep((LimitSpeedRatio * 100L).toLong())
                            miliSec = 0
                        }
                    }
                }
                catch (e : IOException){
                    Log.e(TAG, e.toString())
                }
                finally {
                    try{
                        IsCaching = false
                        dataSource.close()
                    }
                    catch (e : Exception){
                        e.printStackTrace()
                    }
                }
            }
        }
    
        fun CleanCache(){
            //删除缓存
            if(!m_uri.startsWith("http") || IsCaching) return
            Log.d(TAG, "Clean cache. Uri = $m_uri")
            simpleCache.getCachedSpans(m_uri)?.forEach { it -> simpleCache.removeSpan(it) }
            CacheByte = 0
        }
    
        fun StopCache(){
            //停止缓存
            if(!m_uri.startsWith("http") || !IsCaching) return
            Log.d(TAG, "Stop cache. Uri = $m_uri")
            IsCaching = false
        }
    
        override fun onCachedBytesRead(cacheSizeBytes: Long, cachedBytesRead: Long) {
    
        }
    
    }

    这里我省略很多东西,比如空间满了之类的…
    之后就是在建立ExoPlayer的时候,将SimpleCache作为参数输入即可

    exoPlayer = MyExoPlayer(MyTrackRenderersFactory(activity, null, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF, videoCnt, audioCnt),
                DefaultTrackSelector())
    simpleCache = SimpleCache(File(m_context.externalCacheDir, "media_cache"), NoOpCacheEvictor())
    cacheDataSourceFactory = CacheDataSourceFactory(simpleCache,  DefaultHttpDataSourceFactory(Util.getUserAgent(m_context, "ExoPlayer"), DefaultBandwidthMeter()),
    FileDataSourceFactory(), null, 0, this)
    videoSource = ExtractorMediaSource(Uri.parse(url), cacheDataSourceFactory, DefaultExtractorsFactory(), null, null, url)
    exoPlayer.prepare(videoSource)
    展开全文
  • Exoplayer使用记录2-加入ffmpeg软解

    千次阅读 2018-02-25 00:36:57
    Exoplayer使用记录2-加入ffmpeg软解By Xdestiny. 2018/2/5概述有时候会碰到手机硬解无法支持的情况,这时候就要考虑使用软解了。如果仔细查询代码的话,其实会发现Exopalyer在硬解不支持的情况下,会优先调用Google...

    Exoplayer使用记录2-加入ffmpeg软解

    By Xdestiny. 2018/2/5

    概述

    有时候会碰到手机硬解无法支持的情况,这时候就要考虑使用软解了。如果仔细查询代码的话,其实会发现Exopalyer在硬解不支持的情况下,会优先调用Google自己的一套软解策略。不过,在某些情况下这个软解策略会失效(例如Android 6.0及以下版本,Exoplayer播放AAC 7.1是有问题的。某些AAC 7.1只能解出6个通道,剩下2个通道混在前面几个通道中。这个是android系统本身导致的BUG,7.0以后没有这个问题)
    提到软解,那当然就是ffmpeg了。

    解决思路

    其实在编译Exoplayer源文件的时候就可以发现,里面的extensions文件夹下有个名为ffmpeg的文件夹。也就是说Exoplayer官方就是支持添加ffmpeg软解的。相关的安装文档为ExoPlayer FFmpeg extension。按照这个文档一步步就可以将ffmpeg加入ExoPlayer中。

    遇到的问题

    当然,添加的过程中肯定还是遇到了一些问题…这里记录如下

    以及删除一些动态库的软连接
    1. 对于windows平台需要使用mingw或者cygwin。注意要用64位的
    2. 将configure文件转换为linux下的档案格式(也就是将\r\n转换为\n)。最好,git拉取ffmpeg时回车符的设置就与unix下一致(git config –global core.autocrlf false)
    3. 所有的路径需要使用windows的格式(D:/…)
    4. 需要设置临时路径(export TMPDIR=C:/cygwin/tmp)
    5. 编译时有可能报错,可以参考http://blog.csdn.net/openswc/article/details/53287144
    6. 调用的时候需要注意将DefaultRenderersFactory中构造函数的参数extensionRendererMode设置为合适的值

    展开全文
  • Exoplayer使用记录1-播放多音轨视频

    千次阅读 2018-02-22 15:36:04
    Exoplayer使用记录1-播放多音轨视频 By Xdestiny. 2018/2/5 概述 ExoPlayer是个好东西,基本上移动端的播放器除了IJKPlayer以外,应该就数这东西了吧。这里做一个系列,记录一下我摸索的一些东西。当然,本人...

    Exoplayer使用记录1-播放多音轨视频

    By Xdestiny. 2018/2/5

    概述

    ExoPlayer是个好东西,基本上移动端的播放器除了IJKPlayer以外,应该就数这东西了吧。这里做一个系列,记录一下我摸索的一些东西。当然,本人并非专门搞播放器的,只是做一个记录而已。
    最近接到一个需求,要求能够播放多音轨的视频。通常来说,视频中各个音轨对应着不同的播放场景,例如多语言、多码率。而现在的要求则是将所有音轨同时进行播放。

    大致思路

    其实一上来就能想到一个方法,就是实现做好预处理,把多个轨道压成一个轨道,这样就没有什么复杂的了。但如果是不能预先处理的情况下呢?
    ExoPlayer有个好处就是有个相当活跃的社区。因此首先去Issue上搜索一下有没有类似的问题。
    搜索后可以发现几个相关的问题
    Exoplayer 2 - play multiple sounds/audio simultaneously (using MergingMediaSource?
    Set the volume of multiple MediaSource’s in a MergingMediaSource
    Background music during video playback
    不过,好吧…似乎没有什么好的思路。干脆换个思路,如果是同时播多个视频呢?搜索一下相关的问题也有一些
    Synchronizing Multiple ExoPlayers
    这个就很好了,官方给了相关的解决方法。照着这个感觉应该OK。大体上来说就是:
    - 重写MediaCodecAudioRenderer中的getMediaClock。因为现在是多个音轨,必须要显式指定一个音轨用于时钟同步
    - 重写DefaultRenderersFactory中的buildAudioRenderers。原本只建立了一个AudioRenderer,现在需要依据视频中音轨的数目建立多个AudioRenderer
    - 重写TrackSelector中的selectTracks。因为原本的代码只考虑了只有一个renderer的情况。

    具体代码

    基本没怎么碰过java,而且又感觉Kotlin很高大上,所以写的很渣,见谅
    重写MediaCodecAudioRenderer

    class MultiMediaCodecAudioRenderer(mainClock : Boolean, mediaCodecSelector : MediaCodecSelector,
                                       drmSessionManager : DrmSessionManager<FrameworkMediaCrypto>?,
                                       playClearSamplesWithoutKeys : Boolean, eventHandler : Handler?,
                                       eventListener : AudioRendererEventListener?, audioCapabilities : AudioCapabilities,
                                       vararg audioProcessors : AudioProcessor)
        : MediaCodecAudioRenderer(mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys, eventHandler,
            eventListener, audioCapabilities, *audioProcessors)
    {
        private val m_mainClock = mainClock
    
        override fun getMediaClock(): MediaClock? {
            if(m_mainClock)
                return super.getMediaClock()
            return null
        }
    
    }

    重写DefaultRenderersFactory

    class MultiTrackRenderersFactory(context : Context, drmSessionManager: DrmSessionManager<FrameworkMediaCrypto>? = null,
                                  @ExtensionRendererMode extensionRendererMode : Int = DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF,
                                  videoTrackCnt : Int = 1, audioTrackCnt : Int = 1)
        : DefaultRenderersFactory(context, drmSessionManager, extensionRendererMode) {
    
        private val m_videoTrackCnt = videoTrackCnt
        private val m_audioTrackCnt = audioTrackCnt
    
        override fun buildAudioRenderers(context: Context?, drmSessionManager: DrmSessionManager<FrameworkMediaCrypto>?, audioProcessors: Array<AudioProcessor>?, eventHandler: Handler?, eventListener: AudioRendererEventListener?, extensionRendererMode: Int, out: ArrayList<Renderer>?) {
            for (i in 0..m_audioTrackCnt - 1) {
                if(audioProcessors == null)
                    out!!.add(MultiMediaCodecAudioRenderer(i == 0, MediaCodecSelector.DEFAULT, drmSessionManager, true,
                            eventHandler, eventListener, AudioCapabilities.getCapabilities(context)))
                else
                    out!!.add(MultiMediaCodecAudioRenderer(i == 0, MediaCodecSelector.DEFAULT, drmSessionManager, true,
                            eventHandler, eventListener, AudioCapabilities.getCapabilities(context), *audioProcessors))
            }
        }
    }

    重写TrackSelector

    class MultiTrackSelector : TrackSelector() {
    
        private val TAG = "MultiTrackSelector"
    
        init {
            Log.d(TAG, "init")
        }
    
        var currentMappedTrackInfo: MappingTrackSelector.MappedTrackInfo? = null
            get() = field
            private set(value){
                field = value
            }
    
        override fun onSelectionActivated(info: Any?) {
            currentMappedTrackInfo = info as MappingTrackSelector.MappedTrackInfo?
        }
    
        override fun selectTracks(rendererCapabilities: Array<out RendererCapabilities>, trackGroups: TrackGroupArray): TrackSelectorResult {
            Log.d(TAG, "renderer count = ${rendererCapabilities.size}. trackGroups count = ${trackGroups.length}")
            val rendererCount = rendererCapabilities.size
            val rendererTrackSelections = arrayOfNulls<TrackSelection>(rendererCount)
    
            //这里先凑合一下
            for(i in rendererCapabilities.indices){
                when(rendererCapabilities[i].trackType){
                    C.TRACK_TYPE_VIDEO->{
                        rendererTrackSelections[i] = FixedTrackSelection(trackGroups[i], 0)
                    }
                    C.TRACK_TYPE_AUDIO->{
                        if(trackGroups.length > i)
                            rendererTrackSelections[i] = FixedTrackSelection(trackGroups[i], 0)
                    }
                    C.TRACK_TYPE_TEXT->{
                        if(trackGroups.length > i)
                            rendererTrackSelections[i] = FixedTrackSelection(trackGroups[i], 0)
                    }
                    else->{
    
                    }
                }
            }
    
            val rendererConfigurations = arrayOfNulls<RendererConfiguration>(rendererCapabilities.size)
            for (i in rendererCapabilities.indices) {
                rendererConfigurations[i] = if (rendererTrackSelections[i] != null) RendererConfiguration.DEFAULT else null
            }
    
            return TrackSelectorResult(trackGroups, TrackSelectionArray(*rendererTrackSelections), null, rendererConfigurations)
        }
    }

    中间可以看到,我省去了原本代码中的一大堆与码率、格式有关的判定,因此是凑合一下。

    展开全文
  • Exoplayer使用记录4-调节音轨中某个频道的声音
  • git地址 https://github.com/MasayukiSuda/ExoPlayerFilter framebuf, glsurfaceview
  • ExoPlayer简单使用

    2020-03-05 11:01:01
    ExoPlayer Library 概述 ExoPlayer是运行在YouTube app Android版本上的视频播放器 ExoPlayer是构建在Android低水平媒体API之上的一个应用层媒体播放器。和Android内置的媒体播放器相比,ExoPlayer有许多优点。...
  • EXOplayer简书

    千次阅读 2016-09-05 15:07:33
    EXOplayer 使用google开源框架Exoplayer开发自定义播放器 【翻译】安卓新播放器EXOplayer介绍 ExoPlayer 开发者指导 EXOplayer API
  • android exoplayer使用

    千次阅读 2017-08-25 15:35:00
     最近公司让研究一个exoplayer播放器,所以在网上找了些资料,记录一下。英语不错的同学可以直接看文档(点击打开链接) 另外附上官方的github地址(https://github.com/google/ExoPlayer) 二.步骤 添加...
  • ExoPlayer使用介绍

    2018-08-13 09:17:45
    版权声明:本文为博主原创...前言:ExoPlayer是google推出的一个应用级的播放框架。接下来我来对它做一个简单的介绍。 ###一,为什么是ExoPlayer? 1.支持更多的格式 我们知道Android 提供的mediaPlayer只支持有限...
  • 使用ExoPlayer首先要创建一个playerr实例 SimpleExoPlayer exoPlayer=new SimpleExoPlayer.Builder(getApplicationContext()).build(); 有了播放器实例我们要在哪里播放 exoPlayer.setVideoSurface(surfaceView...
  • 使用ExoPlayer播放res/raw中音频资源

    千次阅读 2017-06-23 17:47:35
    前言关于ExoPlayer的使用,很多前人已经帮我们翻译了官方文档,例如ExoPlayer使用,这里不再阐述。 但是上述文章一般就是将官方文档翻译一下,针对具体的使用,可能会遇到很多难以解决问题。正文某天,我想用...
  • EXOplayer

    2017-12-13 11:52:43
    使用google开源框架Exoplayer开发自定义播放器 【翻译】安卓新播放器EXOplayer介绍 ExoPlayer 开发者指导 EXOplayer API 转载于:https://juejin.im/post/5a31148b51882503eb4b4756...
  • 使用ExoPlayer进行媒体流 此存储库中的代码进行。 如果您想开始使用那么代码实验室是一个不错的起点。
  • ExoPlayer简单使用帮助类

    千次阅读 2019-06-04 15:54:49
    最简单使用exoplayer工具类(带视频缓存) /** * Created on 2019/05/29. * interface by * * @author fengzimin */ public class SimpleExoPlayerHelper { private final Context mContext; private ...
  • ExoPlayer使用之自定义UI界面

    万次阅读 2017-11-16 14:51:53
    前言本篇博文讲解的内容是使用EXOPlayer应该如何进行自定义UI界面,达到自己满意的项目效果,主要讲解的是自定义这方面的思路,该怎么入手,确定方向。 切入点我们按照自定义从浅及深的程度来进行,以自定义视频播放...
  • Exoplayer 基本使用的方法

    千次阅读 2018-03-04 23:59:10
    废话不多说,一步步实现...打开 Exoplayer官网,添加需要的依赖。 public class MainActivity extends AppCompatActivity { private PlayerView mPlayerView; private SimpleExoPlayer mPlayer; @Override ...
  • ExoPlayer官方中文使用文档

    千次阅读 2019-06-19 19:47:10
    在这之前笔者使用原生的MediaPlayer、B站开源的IJKVideoView等播放器。知道发现ExoPlayer,这款由YouTube开发的播放器真的是非常强大。对于自定义播放器非常友好,里面讲很多模块抽象成独立的组件可供使用者自行定制...
  • ExoPlayer简单介绍与使用 简单介绍 ExoPlayer是运行在YouTobe app上的视频播放器。它功能强大的同时又兼容低版本Android设备,在ExoPlayer V2版本上最低支持 android 16 也就是android 4.1版本。 功能强大在支持除...
  • 一、简要介绍ExoPlayer Android框架本身提供了MediaPlayer来实现媒体播放。还提供了其他媒体api框架,如MediaCodec、AudioTrack和MediaDrm,可用于构建自定义媒体播放器解决方案。 ExoPlayer是一款开源的应用级媒体...
  • 怎么使用 exoplayer

    2017-02-16 13:10:33
    欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和图片上传 LaTex数学公式 UML序列图和流程图 ...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 321
精华内容 128
关键字:

exoplayer使用