Как получить длительность синхронизированного текста 3gpp-tt (субтитры или скрытые заголовки) через MediaExtractor - PullRequest
0 голосов
/ 22 сентября 2019

Сводка

Я извлекаю данные text / 3gpp-tt из файлов mp4.Как я могу получить «конечное» время синхронизированного текстового элемента (то есть, начиная с TimeOfItem + durationOfTheItem)?

Я знаю, что это возможно с FFmpeg (я действительно делал это раньше), но есть ли более простой способвокруг?

Фон

Я делаю андроид-активность, чтобы показать что-то вроде сценария фильма.Это почти сделано.

Единственная функция, которую я не реализовал, - это просто добавление дополнительной новой строки между двумя строками, интервал которых превышает определенное количество времени (например, одну секунду).

Интервал - это не "initialTimeOfTheCurrentItem - initialTimeOfThePreviousItem", а "initialTimeOfTheCurrentItem - ENDingTimeOfThePreviousItem".

Android MediaExtractor имеет метод для получения времени начала, но, похоже, у него нет метода для определения продолжительности или окончаниявремя.

Код

Пока у меня есть этот код.Мне не нравится переменная "pseudoDuration".

    private void uriToTextView(Uri uri, TextView textView) {
        FileDescriptor fileDescriptor = uriToFileDescriptor(uri);
        if (fileDescriptor == null) {
            textView.append("ERROR: cannot open the uri\n");
            return;
        }

        MediaExtractor mediaExtractor = fileDescriptorToMediaExtractor(fileDescriptor);
        if (mediaExtractor == null) {
            textView.append("ERROR: cannot open media extractor\n");
            return;
        }

        int timedTextTrack = mediaExtractorToTimedTextTrack(mediaExtractor);
        if (timedTextTrack < 0) {
            textView.append("No timed text found\n");
            return;
        }
        mediaExtractor.selectTrack(timedTextTrack);

        ByteBuffer inputBuffer = ByteBuffer.allocate(2048);
        long lastTime = 0;
        int readSize;
        while ((readSize = mediaExtractor.readSampleData(inputBuffer, 0)) >= 0) {
            long startTime = mediaExtractor.getSampleTime();

            short textLength = inputBuffer.getShort();
            if (textLength != readSize - 2) {
                textView.append("ERROR: length mismatch\n");
            }

            // I suppose I can get the duration like
            // "long duration = mediaExtractor.XXXXX"
            //
            long pseudoDuration = textLength * 70000;

            byte[] oneLineByteArray = Arrays.copyOfRange(inputBuffer.array(), 2, readSize);
            String oneLine = new String(oneLineByteArray, StandardCharsets.UTF_8);
            if (oneLine.length() > 0) {
                if (!oneLine.endsWith("\n"))
                    oneLine += "\n";
                if (startTime - lastTime > 1000000)
                    textView.append("\n");
                textView.append(oneLine);
                lastTime = startTime + pseudoDuration;
            }
            mediaExtractor.advance();
        }
        mediaExtractor.release();
    }

    private FileDescriptor uriToFileDescriptor(Uri uri) {
        ParcelFileDescriptor parcelFileDescriptor;
        try {
            parcelFileDescriptor = this.getContentResolver().openFileDescriptor(uri, "r");
        } catch (java.io.IOException e) {
            return null;
        }
        if (parcelFileDescriptor == null)
            return null;
        return parcelFileDescriptor.getFileDescriptor();
    }

    private MediaExtractor fileDescriptorToMediaExtractor(FileDescriptor fileDescriptor) {
        MediaExtractor mediaExtractor = new MediaExtractor();
        try {
            mediaExtractor.setDataSource(fileDescriptor);
        } catch (java.io.IOException e) {
            return null;
        }
        return mediaExtractor;
    }

    private int mediaExtractorToTimedTextTrack(MediaExtractor mediaExtractor) {
        int numTracks = mediaExtractor.getTrackCount();
        for (int i = 0; i < numTracks; i++) {
            MediaFormat mediaFormat = mediaExtractor.getTrackFormat(i);
            String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
            if (mime != null && mime.equalsIgnoreCase("text/3gpp-tt"))
                return i;
        }
        return -1;
    }

Results

Я ожидаю получить продолжительность вместе с длиной текста и самим текстом.(См. https://tools.ietf.org/html/rfc4396#section-4.7, чтобы найти SDUR непосредственно перед TLEN и текстовой строкой.)

Но метод MediaExtractor # readSampleData заполняет данный буфер только TLEN и текстовой строкой.

И этокажется, что нет способа получить длительность через MediaExtractor.

...