您好,登錄后才能下訂單哦!
小編給大家分享一下Android如何實現(xiàn)視頻字幕Subtitle和橫豎屏切換示例,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
系統(tǒng)自帶的VideoView有些視頻格式不支持,那么我們可以用第三方實現(xiàn)的VideoView替代系統(tǒng)的來播放視頻,比較流行的有ijkplayer、vitamio。
最近有個需求就是需要給視頻添加字幕,其實也挺簡單的。字幕比較常用的格式是srt,實際它就是文本,把它解析出來,然后根據(jù)時間再展示就OK。還有就是實現(xiàn)了即使旋轉(zhuǎn)按鈕關(guān)閉,根據(jù)方向感應(yīng)器也能做到橫豎屏切換。
本文用的是系統(tǒng)VideoView,然后播放sd卡中的視頻來作為演示(源碼中帶有f2.mp4和f2.srt,運行時拷貝到sd卡就行)。下面簡單介紹一下源碼:
MainActivity包括顯示字幕和如何實現(xiàn)橫豎屏如何切換:
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;// 用于記錄是否關(guān)閉屏幕旋轉(zhuǎn),0為關(guān)閉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執(zhí)行一次showSRT(),根據(jù)時間匹配顯示哪句字幕 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代表開啟自動旋轉(zhuǎn)true,0代表未開啟自動旋轉(zhuǎn)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); //設(shè)置視頻控制器 // videoView.setMediaController(new MediaController(this)); //播放完成回調(diào) videoView.setOnCompletionListener( new MyPlayerOnCompletionListener()); videoView.setOnPreparedListener(new OnPreparedListener() { //@Override public void onPrepared(MediaPlayer mp) { totalDuration=videoView.getDuration(); if (mTotalTime != null) mTotalTime.setText("/"+generateTime(totalDuration)); } }); //設(shè)置視頻路徑 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="標(biāo)清"; 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", 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(); /** * 這里點擊按鈕轉(zhuǎn)屏,用戶5秒內(nèi)不轉(zhuǎn)屏幕,將自動識別當(dāng)前屏幕方向 */ 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() { // 手動旋轉(zhuǎn)屏幕,5s后會執(zhí)行感應(yīng)的方向 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為了適應(yīng)一開始就有空行以及其他不符格式的空行情況 if (parseStrs.length < 3) { sb.delete(0, sb.length());// 清空,否則影響下一個字幕元素的解析</i> continue; } SRT srt = new SRT(); // 解析開始和結(jié)束時間 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("結(jié)束:" + 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); // 設(shè)置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執(zhí)行一次()取 } 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;//找到后就沒必要繼續(xù)遍歷下去,節(jié)約資源 } } } }
運行效果圖:
Android是一種基于Linux內(nèi)核的自由及開放源代碼的操作系統(tǒng),主要使用于移動設(shè)備,如智能手機和平板電腦,由美國Google公司和開放手機聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。
以上是“Android如何實現(xiàn)視頻字幕Subtitle和橫豎屏切換示例”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。