
系统自带的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<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.setBackground@R_301_6004@(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<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() { @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",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 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 block BufferedReader 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); // 设置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<srtList.size();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实现在横竖屏切换时页面信息不被重置的示例分享Android 屏幕横竖切换详解Android实现屏幕旋转方法总结解决Android手机屏幕横竖屏切换解析Android横竖屏切换的问题 总结以上是内存溢出为你收集整理的Android 实现视频字幕Subtitle和横竖屏切换示例全部内容,希望文章能够帮你解决Android 实现视频字幕Subtitle和横竖屏切换示例所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)