欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android SRT字幕文件基礎(chǔ)操作講解

 更新時間:2023年01月16日 15:04:55   作者:FranzLiszt1847  
這篇文章主要介紹了Android SRT字幕文件基礎(chǔ)操作,SRT的數(shù)據(jù)格式是通過以上單個數(shù)據(jù)節(jié)點可以提供一個大致的思路是:先定位一個數(shù)據(jù)節(jié)點的固定格式,然后將一行一行的讀取到數(shù)據(jù)

簡介

需要在視頻播放時,同步顯示字幕,市面上主流的字幕文件一般為SRT文件,一般流程為:從服務(wù)器請求一個url地址,此為zip字幕壓縮文件,一般需要請求url,下載zip文件,解析zip文件得到字幕srt文件,最后進(jìn)行顯示

下載

請求就不在此多言了,每個服務(wù)器請求體,返回題各異,沒有參考價值。

下載zip文件我們需要在本地創(chuàng)建一個本地文件夾用來存儲此文件。

創(chuàng)建文件夾

 public String createDirectory(String name) {
        File dir = new File(BaseApplication.getContext().getCacheDir(), name);
        File file = BaseApplication.getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
        if (file != null) {
            dir = new File(file, name);
        }
        if (!dir.exists()) {
           dir.mkdirs();
        }
        return dir.toString();
    }

文件下載

文件下載使用的開源框架Filedownloader

 implementation 'com.liulishuo.filedownloader:library:1.7.7'//download

參數(shù)一:下載地址

參數(shù)二:文件存儲地址

參數(shù)三:回調(diào)

從外部傳入需要的下載參數(shù),然后通過callback回調(diào)出去,進(jìn)行頁面更新操作

public void StartDownloadFile(String url,String path,FileDownloaderCallback callback){
        FileDownloader.getImpl().create(url).setPath(path,true).setListener(new FileDownloadListener() {
            @Override
            protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                callback.start();
            }
            @Override
            protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
            }
            @Override
            protected void completed(BaseDownloadTask task) {
                callback.completed(task.getPath());
            }
            @Override
            protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
            }
            @Override
            protected void error(BaseDownloadTask task, Throwable e) {
                callback.failed();
            }
            @Override
            protected void warn(BaseDownloadTask task) {
            }
        }).start();
    }

下載調(diào)用以及文件解析調(diào)用

此處建立文件下載文件夾以及解析完成的文件夾地址,然后通過調(diào)用上述filedownloader文件下載回調(diào),然后在下載完成的回調(diào)中進(jìn)行文件zip解析

 public void download(String url,String title,DownloadResultCallback callback){
        String input = "InputDirectory";
        String output = "OutputDirectory";
        String inPath = FileUtils.getInstance().createDirectory(input);
        String outPath = FileUtils.getInstance().createDirectory(output);
        String sub = FileUtils.getInstance().createFile(inPath,"subTitleFile"+ File.separator);
        DownloadUtils.getInstance().StartDownloadFile(url, sub, new DownloadUtils.FileDownloaderCallback() {
            @Override
            public void start() {
                callback.downloadStart();
            }
            @Override
            public void completed(String inputPath) {
                callback.downloadSuccess();
                String path = inputPath + "/" + title +".zip";
                try {
                    ZipUtils.UnZipFolder(path,outPath);
                    callback.resolveSuccess();
                } catch (Exception e) {
                    callback.resolveFailed(e.getMessage());
                    e.printStackTrace();
                }
            }
            @Override
            public void failed() {
                callback.downloadFailed();
            }
        });
    }

解析

ZIP文件解析

此處被上述調(diào)用,用于zip文件解析

參數(shù)一:需要被解析的zip文件地址

參數(shù)二:輸出文件夾地址

public class ZipUtils {
    public static void UnZipFolder(String zipFileString, String outPathString)throws Exception {
        java.util.zip.ZipInputStream inZip = new java.util.zip.ZipInputStream(new java.io.FileInputStream(zipFileString));
        java.util.zip.ZipEntry zipEntry;
        String szName = "";
        while ((zipEntry = inZip.getNextEntry()) != null) {
            szName = zipEntry.getName();
            if (zipEntry.isDirectory()) {
                // get the folder name of the widget
                szName = szName.substring(0, szName.length() - 1);
                java.io.File folder = new java.io.File(outPathString + java.io.File.separator + szName);
                folder.mkdirs();
            } else {
                java.io.File file = new java.io.File(outPathString + java.io.File.separator + szName);
                file.createNewFile();
                // get the output stream of the file
                java.io.FileOutputStream out = new java.io.FileOutputStream(file);
                int len;
                byte[] buffer = new byte[1024];
                // read (len) bytes into buffer
                while ((len = inZip.read(buffer)) != -1) {
                    // write (len) byte from buffer at the position 0
                    out.write(buffer, 0, len);
                    out.flush();
                }
                out.close();
            }
        }//end of while
        inZip.close();
    }//end o
}

外部引用

參數(shù)一:下載url地址

參數(shù)二:存儲文件夾名稱

參數(shù)三:callback

上述zip文件下載以及zip文件解析為一個封裝類,此處為在外部傳入?yún)?shù),通過回調(diào)進(jìn)行頁面更新,然后在resolveSuccess()方法中進(jìn)行異步操作(此方法代表zip文件被下載成功并且已被成功解析)

private void download(){
        if (titleBeanList == null || titleBeanList.size() == 0)return;
        if (curSubTitlePos == 0)return;
        DownloadUtils.getInstance().download(titleBeanList.get(curSubTitlePos).getSub(), titleBeanList.get(curSubTitlePos).getT_name(), new DownloadUtils.DownloadResultCallback() {
            @Override
            public void downloadStart() {
                Log.d(TAG,"download start");
            }
            @Override
            public void downloadSuccess() {
                Log.d(TAG,"download success");
            }
            @Override
            public void downloadFailed() {
                Log.d(TAG,"download fail");
            }
            @Override
            public void resolveSuccess() {
                Log.d(TAG,"resolve success");
                handler.sendEmptyMessage(6);
            }
            @Override
            public void resolveFailed(String failMsg) {
                Log.d(TAG,"resolve error:"+failMsg);
            }
        });
    }

轉(zhuǎn)換

轉(zhuǎn)換SRT字幕文件

通過將本地的SRT字幕文件轉(zhuǎn)為相對應(yīng)集合實體數(shù)據(jù),具體實體類型根據(jù)SRT文件內(nèi)容而定

 public static List<SrtEntity> getSrtInfoList(String srtPath){
        List<SrtEntity> srtList = new ArrayList<>();
        try {
            InputStreamReader read = new InputStreamReader(new FileInputStream(srtPath), "utf-8");
            BufferedReader bufferedReader = new BufferedReader(read);
            String textLine;
            CursorStatus cursorStatus = CursorStatus.NONE;
            SrtEntity entity = null;
            while ((textLine = bufferedReader.readLine()) != null){
                textLine = textLine.trim();
                if (cursorStatus == CursorStatus.NONE) {
                    if (textLine.isEmpty()) {
                        continue;
                    }
                    if (!isNumeric(textLine)){
                        continue;
                    }
                    // New cue
                    entity = new SrtEntity();
                    // First textLine is the cue number
                    try {
                        entity.setNumber(Integer.parseInt(textLine));
                    } catch (NumberFormatException e) {
                    }
                    cursorStatus = CursorStatus.CUE_ID;
                    continue;
                }
                // Second textLine defines the start and end time codes
                // 00:01:21,456 --> 00:01:23,417
                if (cursorStatus == CursorStatus.CUE_ID) {
                    if (!textLine.substring(13, 16).equals("-->")) {
                        throw new Exception(String.format(
                                "Timecode textLine is badly formated: %s", textLine));
                    }
                    entity.setBg(parseTimeCode(textLine.substring(0, 12)));
                    entity.setEd(parseTimeCode(textLine.substring(17)));
                    cursorStatus = CursorStatus.CUE_TIMECODE;
                    continue;
                }
                // Following lines are the cue lines
                if (!textLine.isEmpty() && (
                        cursorStatus == CursorStatus.CUE_TIMECODE ||
                                cursorStatus ==  CursorStatus.CUE_TEXT)) {
                    entity.addLine(textLine);
                    cursorStatus = CursorStatus.CUE_TEXT;
                    continue;
                }
                if (cursorStatus == CursorStatus.CUE_TIMECODE && textLine.isEmpty()) {
                    entity.addLine(textLine);
                    cursorStatus = CursorStatus.CUE_TEXT;
                    continue;
                }
                if (cursorStatus == CursorStatus.CUE_TEXT && textLine.isEmpty()) {
                    // End of cue
                    srtList.add(entity);
                    entity = null;
                    cursorStatus = CursorStatus.NONE;
                    continue;
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            Log.e(TAG, e.getMessage());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.e(TAG, e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, e.getMessage());
        }
        return srtList;
    }

獲取SRT文件list實體數(shù)據(jù)

通過以上步驟之后,即可將SRT文件轉(zhuǎn)為相對應(yīng)的list實體數(shù)據(jù),最后與視頻聲音進(jìn)行同步即可達(dá)到字幕與聲音同步的效果

        String outPath = FileUtils.getInstance().createDirectory("OutputDirectory");
        String path = outPath +"/" +titleBeanList.get(curSubTitlePos).getT_name();
        srtEntityList.addAll(SrtParser.getSrtInfoList(path));

顯示

字幕顯示

然后通過獲取字幕文件的片段的開始時間與結(jié)束時間,若當(dāng)前視頻的播放進(jìn)度在此范圍之內(nèi),即顯示字幕,否則繼續(xù)尋找;

private void showSubTitle(){
        if (srtEntityList == null || srtEntityList.size() == 0)return;
        for (int i = curSubTitleNum; i < srtEntityList.size(); i++) {
            long start = srtEntityList.get(i).getBg().getTime()+subtitleSpeed;
            long end = srtEntityList.get(i).getEd().getTime()+subtitleSpeed;
            if (curProgress >= start && curProgress <= end){
                /**
                 * 字幕與進(jìn)度相匹配*/
                binding.VideoPlay.setSubTitle(srtEntityList.get(i).content.getText());
                curSubTitleNum = i;
                break;
            }
        }
    }

若用戶往前拖動視頻進(jìn)度條,則將字幕文件片段下標(biāo)置為0,從頭開始匹配

 if (currentPosition - curProgress < 0){
                            //seek --
                            curSubTitleNum = 0;
                        }

到此這篇關(guān)于Android SRT字幕文件基礎(chǔ)操作講解的文章就介紹到這了,更多相關(guān)Android SRT字幕文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論