一种播放远程 TS 格式媒体文件的新方案
作者:Changing Lin
- 2021 年 12 月 23 日
本文字数:2062 字
阅读完需:约 7 分钟
1.背景
有一个需求是,有一个录音回放页面,支持播放服务器上的录像文件,容器格式为 TS,音频编码为 opus,视频为 h264。尝试使用 Google ExoPlayer 来播放,但发现有画面无声音,原因是不支持音频对应的 pid,无正确解析。今天尝试使用 vlc 库来处理,实践证明,vlc 的兼容性会更强一些,可以正常实现播放的需求,音频、视频解码正常。
2.集成与编译问题修复
修改 build.gradle 添加 libvlc 依赖:
implementation 'org.videolan.android:libvlc-all:3.4.7'
复制代码
可能出现的编译失败报错
More than one file was found with OS independent path 'lib/arm64-v8a/libc++_shared.so'
复制代码
解决方法:
packagingOptions {
exclude 'META-INF/androidx.legacy_legacy-support-v4.version'
exclude 'META-INF/annotation-experimental_release.kotlin_module'
pickFirst 'lib/arm64-v8a/libc++_shared.so' // 添加这两行
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
}
复制代码
2.原理
activity_player.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:background="@android:color/background_dark">
<org.videolan.libvlc.util.VLCVideoLayout
android:id="@+id/video_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"/>
</FrameLayout>
复制代码
PlayerActivity.java
/*****************************************************************************
* JavaActivity.java
*****************************************************************************
* Copyright (C) 2016-2019 VideoLAN
* All rights reserved.
*
* This software may be modified and distributed under the terms
* of the BSD license. See the LICENSE file for details.
*****************************************************************************/
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.appcompat.app.AppCompatActivity;
import com.besmart.annotation.BindPath;
import com.nufront.trunking.common.basic.BaseActivity;
import com.nufront.trunking.common.system.LogUtil;
import com.nufront.trunking.common.system.ToastUtil;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;
import org.videolan.libvlc.util.VLCVideoLayout;
import java.util.ArrayList;
public class PlayerActivity extends BaseActivity {
private static final boolean USE_TEXTURE_VIEW = false;
private static final boolean ENABLE_SUBTITLES = true;
private static final String ASSET_FILENAME = "bbb.m4v";
private VLCVideoLayout mVideoLayout = null;
private LibVLC mLibVLC = null;
private MediaPlayer mMediaPlayer = null;
private String mRemoteUrl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (null == getIntent() || !getIntent().hasExtra("url")){
ToastUtil.showToast(getApplication(), R.string.config_bundle_miss_data_tip);
finish();
return;
}
// 格式为:http://ip:port/xxx.ts
mRemoteUrl = getIntent().getStringExtra("url");
LogUtil.printE(PlayerActivity.class, "播放地址: "+mRemoteUrl);
setContentView(R.layout.activity_vlc);
final ArrayList<String> args = new ArrayList<>();
args.add("-vvv");
mLibVLC = new LibVLC(this, args);
mMediaPlayer = new MediaPlayer(mLibVLC);
mVideoLayout = findViewById(R.id.video_layout);
}
@Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.release();
mLibVLC.release();
}
@Override
protected void onStart() {
super.onStart();
mMediaPlayer.attachViews(mVideoLayout, null, ENABLE_SUBTITLES, USE_TEXTURE_VIEW);
final Media media = new Media(mLibVLC, Uri.parse(mRemoteUrl));
mMediaPlayer.setMedia(media);
media.release();
mMediaPlayer.play();
}
@Override
protected void onStop() {
super.onStop();
mMediaPlayer.stop();
mMediaPlayer.detachViews();
}
}
复制代码
划线
评论
复制
发布于: 2 小时前
版权声明: 本文为 InfoQ 作者【Changing Lin】的原创文章。
原文链接:【http://xie.infoq.cn/article/e8cd89a39d1741615b84899e0】。文章转载请联系作者。
Changing Lin
关注
获得机遇的手段远超于固有常规之上~ 2020.04.29 加入
我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。
评论