Android 实现视频字幕Subtitle和横竖屏切换
转载请标明地址:http://blog.csdn.net/gaolei1201/article/details/62041478
系统自带的VideoView有些视频格式不支持,那么我们可以用第三方实现的VideoView替代系统的来播放视频,比较流行的有ijkplayer、vitamio。
最近有个需求就是需要给视频添加字幕,其实也挺简单的。字幕比较常用的格式是srt,实际它就是文本,把它解析出来,然后根据时间再展示就OK。还有就是实现了即使旋转按钮关闭,根据方向感应器也能做到横竖屏切换。
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<VideoPathObject> videopathList=new ArrayList<VideoPathObject>();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;}}};@Overrideprotected 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 blocke.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() {//@Overridepublic 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 {@Overridepublic 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<VideoPathObject> 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() {@Overridepublic 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() {@Overridepublic void run() {// TODO Auto-generated method stubsetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);Log.d("gaolei", "SCREEN_ORIENTATION_FULL_SENSOR"); }}, 5000);}@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {case MotionEvent.ACTION_DOWN: {showOrHideController();break;}}return false;}@Overridepublic void onClick(View view) {// TODO Auto-generated method stubswitch(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 ArrayList<SRT>srtList;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 blockBufferedReader br = new BufferedReader(new InputStreamReader(inputStream,"GB2312"));String line = null;srtList = new ArrayList<SRT>();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());// 清空,否则影响下一个字幕元素的解析</i>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);// 设置SRTsrt.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 blocke.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<srtList.size();i++){SRT srtbean =srtList.get(i);if (currentPosition > srtbean.getBeginTime()&& currentPosition < srtbean.getEndTime()) {tvSrt.setText(srtbean.getSrtBody());//显示过的就删掉,提高查询效率srtList.remove(i);break;//找到后就没必要继续遍历下去,节约资源}}}
}
运行效果图:
![](/assets/blank.gif)
![](/assets/blank.gif)
Android 实现视频字幕Subtitle和横竖屏切换相关推荐
- android 视频播放器 加载字幕,Android 实现视频字幕Subtitle和横竖屏切换示例
系统自带的VideoView有些视频格式不支持,那么我们可以用第三方实现的VideoView替代系统的来播放视频,比较流行的有ijkplayer.vitamio. 最近有个需求就是需要给视频添加字幕, ...
- android dialog横屏,解决dialog在横竖屏切换时消失
以AlertDialog为例 一.将AlertDialog视图封装在dialogfragment(fragmentdeAlertDialog子类)实例中 package com.example.t; ...
- android电视横竖屏切换在哪里,Android横竖屏切换总结
之前在网上看到博客说Activity横竖屏切换的规律如下: (1)不设置android:configChanges,竖屏切换到横屏调用一次生命周期,横屏切竖屏调用两次生命周期. (2)设置 andro ...
- android横竖屏切换函数,Android横竖屏切换小结.PDF
Android横竖屏切换小结 Android横竖屏切换小结 Android手机或平板都会存在横竖屏切换的功能,通常是由物理重力感应触发的,但是 有时候也不尽然,通常在设置里面我们可以对手机的横竖屏切换 ...
- Android横竖屏切换小结
(老样子,图片啥的详细文档,可以下载后观看 http://files.cnblogs.com/franksunny/635350788930000000.pdf) Android手机或平板都会存在横竖 ...
- Android横竖屏切换相关知识点
转载自:http://www.cnblogs.com/franksunny/p/3714442.html (老样子,图片啥的详细文档,可以下载后观看 http://files.cnblogs.com/ ...
- Android横竖屏切换小结(重建、非重建Activity)
来自:http://www.cnblogs.com/franksunny/p/3714442.html (老样子,图片啥的详细文档,可以下载后观看 http://files.cnblogs.com/f ...
- Android 横竖屏切换小结
(自己体会:每次横竖屏自动切时都会run Activity的onCreate,即相当后重新进入Activity初始化一样:) 转自:http://www.cnblogs.com/franksunny/ ...
- Android横竖屏切换
尊重原创,本文转载自 http://www.cnblogs.com/franksunny/p/3714442.html Android横竖屏切换小结 (老样子,图片啥的详细文档,可以下载后观看 htt ...
最新文章
- Linux那些事儿 之 戏说USB(5)我是谁
- Interview:人工智能岗位面试—人工智能岗位求职之机器学习算法工程师必备知识框架结构图
- git回退的四种操作
- leetcode875.KokoEatingBananas
- 仿复制粘贴功能,长按弹出tips的实现
- c语言数据结构单链表输出链表操作,单链表一系列操作c语言实现(按照严蔚敏那本数据结构编写)...
- vi/vim替换字符
- 关于Win10系统的封装
- 人工神经网络概念及组成,人工神经网络基本概念
- C——识别键盘按下模拟键盘按下
- 【转载】TextView源码解析
- CSS3 设置模糊背景图片
- 指尖检测的新方法几种
- python起笔落笔_书法讲究的是起笔和落笔落是什么意思
- 【论文阅读】改进的基于均值滤波的单幅图像去雾算法研究
- HADOOP与HDFS数据压缩格式
- 基于jsp(java)网络教学平台系统的设计和开发(含源文件)
- python进行图像滤波_Python图像滤波处理操作示例【基于ImageFilter类】
- 科全可拓展免费进销存系统
- 献给86,87,88,89年出生的80后
热门文章
- Jsoup,一款超好用的HTML文本解析Java工具
- (四十六:2021.08.17)《医疗物联网单导联心电波心房颤动检测研究》
- 个人喜欢的小于100K的迷你绿色软件合集
- Python 实用爬虫-04-使用 BeautifulSoup 去水印下载 CSDN 博客图片
- 数字图像处理基础知识
- 关于BitmapFactory.decodeStream(is)方法无法正常解码为Bitmap对象的解决方法
- 计算机 继续教育培训心得体会,继续教育培训学习心得
- Beego脱坑(一)Beego简介和安装
- Vue设置部分页面缓存,设置部分页面不缓存
- 面试阿里P6,过关斩将直通2面,结果3面找了个架构师来吊打我?