系统自带的VideoView有些视频格式不支持,那么我们可以用第三方实现的VideoView替代系统的来播放视频,比较流行的有ijkplayer、vitamio。

最近有个需求就是需要给视频添加字幕,其实也挺简单的。字幕比较常用的格式是srt,实际它就是文本,把它解析出来,然后根据时间再展示就OK。还有就是实现了即使旋转按钮关闭,根据方向感应器也能做到横竖屏切换。

本文用的是系统VideoView,然后播放sd卡中的视频来作为演示(源码中带有f2.mp4和f2.srt,运行时拷贝到sd卡就行)。下面简单介绍一下源码:

MainActivity包括显示字幕和如何实现横竖屏如何切换:

public class SubtitleActivity extends Activity implements View.OnClickListener,OnTouchListener{

private VideoView videoView ;

TextView tvSrt, mCurrentTime,mTotalTime,resolution_switch,mediacontroller_file_name;

ImageView mediacontroller_play_pause,switch_screen;

private SeekBar progress_seekbar;

private AudioManager mAM;

private long totalDuration;

private boolean mShowing = true, mDragging,isResolution;

private static final int PARSE_SRT = 0;

private static final int FADE_OUT = 1;

private static final int SHOW_PROGRESS = 2;

private static final int CHANGE_VIDEOVIEW_BG = 3;

private static final int SCREEN_ORIENTATION_USER = 4;

private static final int sDefaultTimeout = 3000;

private RelativeLayout videoview_layout, mMediaController;

private ListView resolution_listview;

private boolean isPortraint = true;

private static int LockScreen = -1;// 用于记录是否关闭屏幕旋转,0为关闭1为开启

private int screenWidth,videoViewHeight;

List videopathList=new ArrayList();

Handler mHandler=new Handler(){

public void handleMessage(Message msg){

long pos;

switch (msg.what) {

case PARSE_SRT:

SrtParser.showSRT(videoView,tvSrt) ;

//每隔500ms执行一次showSRT(),根据时间匹配显示哪句字幕

mHandler.sendEmptyMessageDelayed(0, 500);

break;

case FADE_OUT:

showOrHideController();

break;

case SHOW_PROGRESS:

pos = setControllerProgress();

if (!mDragging && mShowing) {

msg = obtainMessage(SHOW_PROGRESS);

sendMessageDelayed(msg, 1000 - (pos % 1000));

}

break;

case CHANGE_VIDEOVIEW_BG:

videoView.setBackgroundColor(0x00000000);

break;

}

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_subtitle);

videoView = (VideoView)this.findViewById(R.id.videoView );

mAM = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

screenWidth = APPApplication.screenWidth;

videoViewHeight = screenWidth * 9 / 16;

tvSrt = (TextView)findViewById(R.id.srt);//项目中显示字幕的控件

mediacontroller_file_name= (TextView)findViewById(R.id.mediacontroller_file_name);

//String[]splitStr=Constant.videoUrl1.split("/");

//mediacontroller_file_name.setText(splitStr[splitStr.length-1]);

mTotalTime = (TextView) findViewById(R.id.mediacontroller_time_total);

mCurrentTime = (TextView) findViewById(R.id.mediacontroller_time_current);

resolution_switch = (TextView) findViewById(R.id.resolution_switch);

mediacontroller_play_pause = (ImageView) findViewById(R.id.mediacontroller_play_pause);

switch_screen = (ImageView) findViewById(R.id.switch_screen);

videoview_layout = (RelativeLayout) findViewById(R.id.videoview_layout);

mediacontroller_play_pause.setOnClickListener(this);

progress_seekbar = (SeekBar) findViewById(R.id.mediacontroller_seekbar);

videoview_layout = (RelativeLayout) findViewById(R.id.videoview_layout);

mMediaController = (RelativeLayout) findViewById(R.id.media_controller);

resolution_listview = (ListView) findViewById(R.id.resolution_listview);

resolution_switch.setOnClickListener(this);

videoView.setOnTouchListener(this);

progress_seekbar.setOnSeekBarChangeListener(mSeekListener);

LayoutParams params = new RelativeLayout.LayoutParams(

LayoutParams.MATCH_PARENT, videoViewHeight);

videoview_layout.setLayoutParams(params);

try {

// 1代表开启自动旋转true,0代表未开启自动旋转false

// Settings.System.getInt(mContext.getContentResolver(),Settings.System.ACCELEROMETER_ROTATION,0);

LockScreen = Settings.System.getInt(getContentResolver(),

Settings.System.ACCELEROMETER_ROTATION);

} catch (SettingNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//String rawUri = "android.resource://" + getPackageName() + "/" + R.raw.renwei;

Uri uri = Uri.parse(Constant.videoUrl1);

//设置视频控制器

// videoView.setMediaController(new MediaController(this));

//播放完成回调

videoView.setOnCompletionListener( new MyPlayerOnCompletionListener());

videoView.setOnPreparedListener(new OnPreparedListener() {

//@Override

public void onPrepared(MediaPlayer mp) {

totalDuration=videoView.getDuration();

if (mTotalTime != null)

mTotalTime.setText("/"+generateTime(totalDuration));

}

});

//设置视频路径

videoView.setVideoURI(uri);

//开始播放视频

videoView.start();

SrtParser.parseSrt(this);

SrtParser.showSRT(videoView,tvSrt) ;

mHandler.sendEmptyMessageDelayed(0, 500);

initVideoResolution();

}

private void initVideoResolution(){

VideoPathObject object1=new VideoPathObject();

object1.videoStatus="超清";

videopathList.add(object1);

VideoPathObject object2=new VideoPathObject();

object2.videoStatus="高清";

videopathList.add(object2);

VideoPathObject object3=new VideoPathObject();

object3.videoStatus="标清";

videopathList.add(object3);

switchResolution(videopathList);

}

class MyPlayerOnCompletionListener implements MediaPlayer.OnCompletionListener {

@Override

public void onCompletion(MediaPlayer mp) {

Toast.makeText( SubtitleActivity.this, "播放完成了", Toast.LENGTH_SHORT).show();

}

}

private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {

public void onStartTrackingTouch(SeekBar bar) {

mDragging = true;

mHandler.removeMessages(SHOW_PROGRESS);

mAM.setStreamMute(AudioManager.STREAM_MUSIC, true);

}

public void onProgressChanged(SeekBar bar, int progress,

boolean fromuser) {

if (!fromuser)

return;

int newposition = (int)(totalDuration * progress) / 1000;

String time = generateTime(newposition);

videoView.seekTo(newposition);

mCurrentTime.setText(time);

}

public void onStopTrackingTouch(SeekBar bar) {

videoView.seekTo(((int)totalDuration * bar.getProgress()) / 1000);

hideMediaController(sDefaultTimeout);

mAM.setStreamMute(AudioManager.STREAM_MUSIC, false);

mDragging = false;

mHandler.sendEmptyMessageDelayed(SHOW_PROGRESS, 1000);

}

};

private void switchResolution(final List videopathList) {

resolution_switch

.setText(videopathList.get(videopathList.size() - 1).videoStatus);

mediacontroller_play_pause.setImageResource(R.drawable.player_play);

final ResolutionAdapter adapter = new ResolutionAdapter(videopathList,

SubtitleActivity.this);

resolution_listview.setAdapter(adapter);

resolution_listview

.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView> arg0, View arg1,

int position, long arg3) {

// TODO Auto-generated method stub

currentPosition = videoView.getCurrentPosition();

//currentPosition = videoView.getCurrentPosition();

//Log.d("gaolei", "currentPosition---------1------"

//+ currentPosition);

VideoPathObject pathObject = videopathList

.get(position);

playVideo(pathObject.videoUrl);

//adapter.changePosition(position);

resolution_switch.setText(pathObject.videoStatus);

resolution_listview.setVisibility(View.GONE);

}

});

}

public void showOrHideController() {

if (mShowing) {

mHandler.removeMessages(SHOW_PROGRESS);

mHandler.removeMessages(FADE_OUT);

mMediaController.setVisibility(View.GONE);

resolution_listview.setVisibility(View.GONE);

mShowing = false;

} else {

mHandler.sendEmptyMessage(SHOW_PROGRESS);

mMediaController.setVisibility(View.VISIBLE);

hideMediaController(sDefaultTimeout);

mShowing = true;

}

}

public void hideMediaController(int sDefaultTimeout) {

mHandler.sendEmptyMessageDelayed(FADE_OUT, sDefaultTimeout);

}

private long setControllerProgress() {

if (videoView == null || mDragging)

return 0;

int position = videoView.getCurrentPosition();

if (progress_seekbar != null) {

if (totalDuration > 0) {

long pos = 1000L * position / totalDuration;

// Log.d("gaolei", "progress--------------" + pos);

progress_seekbar.setProgress((int) pos);

}

int percent = videoView.getBufferPercentage();

progress_seekbar.setSecondaryProgress(percent * 10);

}

if (mCurrentTime != null)

mCurrentTime.setText(generateTime(position));

return position;

}

private static String generateTime(long position) {

int totalSeconds = (int) (position / 1000);

int seconds = totalSeconds % 60;

int minutes = (totalSeconds / 60) % 60;

int hours = totalSeconds / 3600;

if (hours > 0) {

return String.format(Locale.US, "%02d:%02d:%02d", hours, minutes,

seconds).toString();

} else {

return String.format(Locale.US, "%02d:%02d", minutes, seconds)

.toString();

}

}

private void updatePausePlay() {

if (videoView.isPlaying()) {

videoView.pause();

mediacontroller_play_pause

.setImageResource(R.drawable.player_pause);

} else {

videoView.start();

mediacontroller_play_pause.setImageResource(R.drawable.player_play);

}

}

public void showResolution(View view) {

if (!isResolution) {

resolution_listview.setVisibility(View.VISIBLE);

isResolution = true;

} else {

resolution_listview.setVisibility(View.GONE);

isResolution = false;

}

}

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {

changeToFullScreen();

Log.d("gaolei", "ORIENTATION_LANDSCAPE-------------");

}

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {

changeToSmallScreen();

Log.d("gaolei", "ORIENTATION_PORTRAIT-------------");

}

}

public void switchScreen(View view) {

if (isPortraint) {

handToFullScreen();

} else {

handToSmallScreen();

}

}

public void handToSmallScreen() {

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);

changeToSmallScreen();

/**

* 这里点击按钮转屏,用户5秒内不转屏幕,将自动识别当前屏幕方向

*/

autoSwitchScreenOrientation();

}

public void handToFullScreen() {

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);

changeToFullScreen();

autoSwitchScreenOrientation();

}

private void changeToFullScreen() {

isPortraint = false;

LayoutParams params = new RelativeLayout.LayoutParams(

LayoutParams.MATCH_PARENT, APPApplication.screenWidth);

videoview_layout.setLayoutParams(params);

videoView.setLayoutParams(params);

WindowManager.LayoutParams windowparams = getWindow().getAttributes();

windowparams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;

getWindow().setAttributes(windowparams);

getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

switch_screen.setImageResource(R.drawable.player_switch_small);

}

private void changeToSmallScreen() {

isPortraint = true;

LayoutParams params = new RelativeLayout.LayoutParams(

LayoutParams.MATCH_PARENT, videoViewHeight);

videoview_layout.setLayoutParams(params);

videoView.setLayoutParams(params);

WindowManager.LayoutParams windowparams = getWindow().getAttributes();

windowparams.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);

getWindow().setAttributes(windowparams);

getWindow()

.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

switch_screen.setImageResource(R.drawable.player_switch_big);

}

public void autoSwitchScreenOrientation() {

//手动旋转屏幕,5s后会执行感应的方向

new Timer().schedule(new TimerTask() {

@Override

public void run() {

// TODO Auto-generated method stub

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);

Log.d("gaolei", "SCREEN_ORIENTATION_FULL_SENSOR");}

}, 5000);

}

@Override

public boolean onTouch(View v, MotionEvent event) {

// TODO Auto-generated method stub

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN: {

showOrHideController();

break;

}

}

return false;

}

@Override

public void onClick(View view) {

// TODO Auto-generated method stub

switch(view.getId()){

case R.id.mediacontroller_play_pause:

Log.d("gaolei", "mediacontroller_play_pause");

updatePausePlay();

break;

case R.id.resolution_switch:

resolution_listview.setVisibility(View.VISIBLE);

break;

}

}

public void jumpToMain(View view){

startActivity(new Intent(this, MainActivity.class));

}

public void onRestart(){

super.onRestart();

videoView.start();

mediacontroller_play_pause.setImageResource(R.drawable.player_play);

}

public void onStop(){

super.onStop();

videoView.pause();

mediacontroller_play_pause.setImageResource(R.drawable.player_pause);

}

}

SrtParser就是解析字幕文件的算法:

public class SrtParser {

public static ArrayListsrtList;

public static int lastEndTime;

/**

* 解析SRT字幕文件

* 字幕路径

*/

public static void parseSrt(Context context) {

InputStream inputStream = null;

try {

// inputStream=context.getResources().openRawResource(R.raw.renwei2);

inputStream = new FileInputStream(Constant.srtUrl1);

// TODO Auto-generated catch block

BufferedReader br = new BufferedReader(new InputStreamReader(

inputStream,"GB2312"));

String line = null;

srtList = new ArrayList();

StringBuffer sb = new StringBuffer();

while ((line = br.readLine()) != null) {

// Log.d("gaolei", "br.readLine()-----------"+br.readLine());

if (!line.equals("")) {

Log.d("gaolei","line-------------------"+ line);

sb.append(line).append("@");

continue;

}

Log.d("gaolei", "sb.toString()-----------"+sb.toString());

String[] parseStrs = sb.toString().split("@");

// 该if为了适应一开始就有空行以及其他不符格式的空行情况

if (parseStrs.length < 3) {

sb.delete(0, sb.length());// 清空,否则影响下一个字幕元素的解析

continue;

}

SRT srt = new SRT();

// 解析开始和结束时间

String timeTotime = parseStrs[1];

int begin_hour = Integer.parseInt(timeTotime.substring(0, 2));

int begin_mintue = Integer.parseInt(timeTotime.substring(3, 5));

int begin_scend = Integer.parseInt(timeTotime.substring(6, 8));

int begin_milli = Integer.parseInt(timeTotime.substring(9, 12));

int beginTime = (begin_hour * 3600 + begin_mintue * 60 + begin_scend)

* 1000 + begin_milli;

int end_hour = Integer.parseInt(timeTotime.substring(17, 19));

int end_mintue = Integer.parseInt(timeTotime.substring(20, 22));

int end_scend = Integer.parseInt(timeTotime.substring(23, 25));

int end_milli = Integer.parseInt(timeTotime.substring(26, 29));

int endTime = (end_hour * 3600 + end_mintue * 60 + end_scend)

* 1000 + end_milli;

System.out.println("开始:" + begin_hour + ":" + begin_mintue +

":"

+ begin_scend + ":" + begin_milli + "=" + beginTime

+ "ms");

System.out.println("结束:" + end_hour + ":" + end_mintue + ":"

+ end_scend + ":" + end_milli + "=" + endTime + "ms");

// 解析字幕文字

String srtBody = "";

// 可能1句字幕,也可能2句及以上。

for (int i = 2; i < parseStrs.length; i++) {

srtBody += parseStrs[i]+ "\n";

}

// 删除最后一个"\n"

srtBody = srtBody.substring(0, srtBody.length() - 1);

// 设置SRT

srt.setBeginTime(beginTime);

srt.setEndTime(endTime);

srt.setSrtBody(new String(srtBody.getBytes(), "UTF-8"));

srtList.add(srt);

sb.delete(0, sb.length());// 清空,否则影响下一个字幕元素的解析

}

lastEndTime=srtList.get(srtList.size()-1).getEndTime();

br.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//每隔500ms执行一次()取

}

public static void showSRT(VideoView videoView,TextView tvSrt) {

// Log.d("gaolei", "srt_map.size()--------------"+srt_map.size());

int currentPosition = videoView.getCurrentPosition();//vv是VideoView播放器

if(currentPosition>lastEndTime){

tvSrt.setVisibility(View.GONE);

return;

}

for(int i=0;i

SRT srtbean =srtList.get(i);

if (currentPosition > srtbean.getBeginTime()

&& currentPosition < srtbean.getEndTime()) {

tvSrt.setText(srtbean.getSrtBody());

//显示过的就删掉,提高查询效率

srtList.remove(i);

break;//找到后就没必要继续遍历下去,节约资源

}

}

}

}

运行效果图:

以上这篇Android 实现视频字幕Subtitle和横竖屏切换示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

android 视频播放器 加载字幕,Android 实现视频字幕Subtitle和横竖屏切换示例相关推荐

  1. Android 视频播放器 (二):使用MediaPlayer播放视频

    在 Android 视频播放器 (一):使用VideoView播放视频 我们讲了一下如何使用VideoView播放视频,了解了基本的播放器的一些知识和内容.也知道VideoView内部封装的就是Med ...

  2. Android 视频播放器JieCaoVideoPlayer使用(防今日头条视频预加载)

    上代码 依赖 compile 'fm.jiecao:jiecaovideoplayer:4.8.3'compile 'com.github.bumptech.glide:glide:3.7.0'com ...

  3. android 仿微信加载框,Android自定义控件——仿微信半透明加载框

    在我们的app中不免回遇到耗时操作,这时我们给个加载框进行过度,使用户体验大大加强. 一.CustomDialog类的编写 package com.daqsoft.jingguan.weight; i ...

  4. Android 实现视频字幕Subtitle和横竖屏切换

    转载请标明地址:http://blog.csdn.net/gaolei1201/article/details/62041478 系统自带的VideoView有些视频格式不支持,那么我们可以用第三方实 ...

  5. Android零基础入门第76节:Activity数据保存和横竖屏切换

    在前面几期学习了Activity的创建.配置.启动和停止,还学了Activity的生命周期,本期一起来学习Activity有关的更多事儿. 一.数据保存 通过上一期 LogCat 窗口打印的日志可以看 ...

  6. android viewpager动态加载图片,Android使用ViewPager加载图片和轮播视频

    作为Android基础组件之一,大家对viewpager已经很熟悉了,网上也有很多使用viewpager来加载图片的案例.但是像微信那样点击图片,可以轮播显示图片和视频的例子却没找到.正巧项目中有需求 ...

  7. android播放器设置中文,Android 视频播放器 (一):使用VideoView播放视频

    一.简介 作为Android开发,我们不可避免的会接触到视频播放,VideoView做为最简单的播放器,我们是不应该不会的. 下面简单介绍一下VideoView: •  VideoView是使用Med ...

  8. Android 视频播放器 (一):使用VideoView播放视频

    一.简介 作为Android开发,我们不可避免的会接触到视频播放,VideoView做为最简单的播放器,我们是不应该不会的. 下面简单介绍一下VideoView: VideoView是使用MediaP ...

  9. android viewpager动态加载页面,Android viewpager中动态添加view并实现伪无限循环的方法...

    本文实例讲述了Android viewpager中动态添加view并实现伪无限循环的方法.分享给大家供大家参考,具体如下: viewpager的使用,大家都熟悉,它可以实现页面之间左右滑动的切换,这里 ...

最新文章

  1. 我的车模我做主 - 精美的车模作品
  2. Linux(RHEL7及CentOS7)下glibc版MySQL5.7.20的安装
  3. 程序员公开上班摸鱼神器!有了它,老板都不好意思打扰你!
  4. TrimPath - Js模板引擎
  5. AnnotationConfigApplicationContext容器初始化
  6. 安全模式 提权_记一次渗透挖洞提权实战
  7. PHP中CURL方法curl_setopt()函数的一些参数
  8. java hashmap 去重_java数组去重的两种方法
  9. mysql查询语法错误_MySQL内部联接查询语法错误
  10. and or not 优先级_我的家乡|我的侠客公测成就奖励大全 成就解锁优先级排名
  11. 2020年秋季学期Python教材推荐与选用参考
  12. |app自动化测试之Appium WebView 技术原理
  13. Win32无边框窗口
  14. SV绿皮书笔记(九)暂时完结
  15. 【深度学习】04-01-自注意力机制(Self-attention)-李宏毅老师2122深度学习课程笔记
  16. 在eclipse上运行html文件
  17. 拼多多商家后台字体加密分析
  18. 【问题解决】java.lang.IllegalStateException异常是什么问题?解决办法
  19. 设置允许从网络访问计算机的用户账户(加入guest组),网络共享
  20. 软件工程职业方向有哪些

热门文章

  1. 唐巧iOS博客好文列表
  2. 3 计算机网络的主要功能,计算机网络的功能主要有哪些?
  3. Linux下使用Netfilter框架编写内核模块(统计协议层ping特定地址丢包数)
  4. P1282 多米诺骨牌
  5. PMP新考纲 敏捷题目 (五)
  6. YII2.0电商平台开发笔记
  7. 现在人工智能自动修复老照片的效果有好?
  8. css绘制梯形图形,及显示矩形图片
  9. 计算图片中矩形间的IOU
  10. 将门CTO沈强:人工智能时代,技术创新将全面引爆商业变革