mirror of
https://github.com/samsonjs/media.git
synced 2026-04-22 14:05:55 +00:00
Support MKV embedded WebVTT captions
This commit is contained in:
parent
b3981be8b9
commit
6b3187ccf1
1 changed files with 45 additions and 2 deletions
|
|
@ -138,6 +138,7 @@ public class MatroskaExtractor implements Extractor {
|
|||
private static final String CODEC_ID_PCM_FLOAT = "A_PCM/FLOAT/IEEE";
|
||||
private static final String CODEC_ID_SUBRIP = "S_TEXT/UTF8";
|
||||
private static final String CODEC_ID_ASS = "S_TEXT/ASS";
|
||||
private static final String CODEC_ID_VTT = "S_TEXT/WEBVTT";
|
||||
private static final String CODEC_ID_VOBSUB = "S_VOBSUB";
|
||||
private static final String CODEC_ID_PGS = "S_HDMV/PGS";
|
||||
private static final String CODEC_ID_DVBSUB = "S_DVBSUB";
|
||||
|
|
@ -323,6 +324,32 @@ public class MatroskaExtractor implements Extractor {
|
|||
/** The format of an SSA timecode. */
|
||||
private static final String SSA_TIMECODE_FORMAT = "%01d:%02d:%02d:%02d";
|
||||
|
||||
/**
|
||||
* A template for the prefix that must be added to each VTT sample.
|
||||
*
|
||||
* <p>The display time of each subtitle is passed as {@code timeUs} to {@link
|
||||
* TrackOutput#sampleMetadata}. The start and end timecodes in this template are relative to
|
||||
* {@code timeUs}. Hence the start timecode is always zero. The 12 byte end timecode starting at
|
||||
* {@link #VTT_PREFIX_END_TIMECODE_OFFSET} is set to a placeholder value, and must be replaced
|
||||
* with the duration of the subtitle.
|
||||
*
|
||||
* <p>Equivalent to the UTF-8 string: "WEBVTT\n\n00:00:00.000 --> 00:00:00.000\n".
|
||||
*/
|
||||
private static final byte[] VTT_PREFIX =
|
||||
new byte[]{
|
||||
87, 69, 66, 86, 84, 84, 10, 10, 48, 48, 58, 48, 48, 58, 48, 48, 46, 48, 48, 48, 32, 45,
|
||||
45, 62, 32, 48, 48, 58, 48, 48, 58, 48, 48, 46, 48, 48, 48, 10
|
||||
};
|
||||
/** The byte offset of the end timecode in {@link #VTT_PREFIX}. */
|
||||
private static final int VTT_PREFIX_END_TIMECODE_OFFSET = 25;
|
||||
/**
|
||||
* The value by which to divide a time in microseconds to convert it to the unit of the last value
|
||||
* in a VTT timecode (milliseconds).
|
||||
*/
|
||||
private static final long VTT_TIMECODE_LAST_VALUE_SCALING_FACTOR = 1000;
|
||||
/** The format of a VTT timecode. */
|
||||
private static final String VTT_TIMECODE_FORMAT = "%02d:%02d:%02d.%03d";
|
||||
|
||||
/** The length in bytes of a WAVEFORMATEX structure. */
|
||||
private static final int WAVE_FORMAT_SIZE = 18;
|
||||
/** Format tag indicating a WAVEFORMATEXTENSIBLE structure. */
|
||||
|
|
@ -1342,7 +1369,8 @@ public class MatroskaExtractor implements Extractor {
|
|||
track.trueHdSampleRechunker.sampleMetadata(
|
||||
track.output, timeUs, flags, size, offset, track.cryptoData);
|
||||
} else {
|
||||
if (CODEC_ID_SUBRIP.equals(track.codecId) || CODEC_ID_ASS.equals(track.codecId)) {
|
||||
if (CODEC_ID_SUBRIP.equals(track.codecId) || CODEC_ID_ASS.equals(track.codecId)
|
||||
|| CODEC_ID_VTT.equals(track.codecId)) {
|
||||
if (blockSampleCount > 1) {
|
||||
Log.w(TAG, "Skipping subtitle sample in laced block.");
|
||||
} else if (blockDurationUs == C.TIME_UNSET) {
|
||||
|
|
@ -1415,6 +1443,9 @@ public class MatroskaExtractor implements Extractor {
|
|||
} else if (CODEC_ID_ASS.equals(track.codecId)) {
|
||||
writeSubtitleSampleData(input, SSA_PREFIX, size);
|
||||
return finishWriteSampleData();
|
||||
} else if (CODEC_ID_VTT.equals(track.codecId)) {
|
||||
writeSubtitleSampleData(input, VTT_PREFIX, size);
|
||||
return finishWriteSampleData();
|
||||
}
|
||||
|
||||
TrackOutput output = track.output;
|
||||
|
|
@ -1641,7 +1672,8 @@ public class MatroskaExtractor implements Extractor {
|
|||
* <p>See documentation on {@link #SSA_DIALOGUE_FORMAT} and {@link #SUBRIP_PREFIX} for why we use
|
||||
* the duration as the end timecode.
|
||||
*
|
||||
* @param codecId The subtitle codec; must be {@link #CODEC_ID_SUBRIP} or {@link #CODEC_ID_ASS}.
|
||||
* @param codecId The subtitle codec; must be {@link #CODEC_ID_SUBRIP}, {@link #CODEC_ID_ASS} or
|
||||
* {@link #CODEC_ID_VTT}.
|
||||
* @param durationUs The duration of the sample, in microseconds.
|
||||
* @param subtitleData The subtitle sample in which to overwrite the end timecode (output
|
||||
* parameter).
|
||||
|
|
@ -1662,6 +1694,12 @@ public class MatroskaExtractor implements Extractor {
|
|||
durationUs, SSA_TIMECODE_FORMAT, SSA_TIMECODE_LAST_VALUE_SCALING_FACTOR);
|
||||
endTimecodeOffset = SSA_PREFIX_END_TIMECODE_OFFSET;
|
||||
break;
|
||||
case CODEC_ID_VTT:
|
||||
endTimecode =
|
||||
formatSubtitleTimecode(
|
||||
durationUs, VTT_TIMECODE_FORMAT, VTT_TIMECODE_LAST_VALUE_SCALING_FACTOR);
|
||||
endTimecodeOffset = VTT_PREFIX_END_TIMECODE_OFFSET;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
|
@ -1830,6 +1868,7 @@ public class MatroskaExtractor implements Extractor {
|
|||
case CODEC_ID_PCM_FLOAT:
|
||||
case CODEC_ID_SUBRIP:
|
||||
case CODEC_ID_ASS:
|
||||
case CODEC_ID_VTT:
|
||||
case CODEC_ID_VOBSUB:
|
||||
case CODEC_ID_PGS:
|
||||
case CODEC_ID_DVBSUB:
|
||||
|
|
@ -2157,6 +2196,9 @@ public class MatroskaExtractor implements Extractor {
|
|||
mimeType = MimeTypes.TEXT_SSA;
|
||||
initializationData = ImmutableList.of(SSA_DIALOGUE_FORMAT, getCodecPrivate(codecId));
|
||||
break;
|
||||
case CODEC_ID_VTT:
|
||||
mimeType = MimeTypes.TEXT_VTT;
|
||||
break;
|
||||
case CODEC_ID_VOBSUB:
|
||||
mimeType = MimeTypes.APPLICATION_VOBSUB;
|
||||
initializationData = ImmutableList.of(getCodecPrivate(codecId));
|
||||
|
|
@ -2245,6 +2287,7 @@ public class MatroskaExtractor implements Extractor {
|
|||
.setColorInfo(colorInfo);
|
||||
} else if (MimeTypes.APPLICATION_SUBRIP.equals(mimeType)
|
||||
|| MimeTypes.TEXT_SSA.equals(mimeType)
|
||||
|| MimeTypes.TEXT_VTT.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_VOBSUB.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_PGS.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_DVBSUBS.equals(mimeType)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue