Android 实现视频字幕Subtitle和横竖屏切换示例

Android 实现视频字幕Subtitle和横竖屏切换示例,第1张

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

系统自带的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和横竖屏切换示例所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1143032.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存