arib-subtitle-timedmetadater
Version:
ARIB subtitle copy as id3 timed-metadata
186 lines (185 loc) • 8.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var arib_mpeg2ts_parser_1 = require("arib-mpeg2ts-parser");
var arib_mpeg2ts_parser_2 = require("arib-mpeg2ts-parser");
var ID3 = /** @class */ (function () {
function ID3() {
}
ID3.metadata_pointer_descriptor = function (program_number) {
var metadata_pointer_descriptor_application_format = Buffer.from([0xFF, 0xFF]);
var metadata_pointer_descriptor_application_format_identifier = Buffer.from([
0x49, 0x44, 0x33, 0x20, // ID3
]);
var metadata_pointer_descriptor_format = Buffer.from([0xFF]);
var metadata_pointer_descriptor_format_identifier = Buffer.from([
0x49, 0x44, 0x33, 0x20 // ID3
]);
var metadata_pointer_descriptor_flags = Buffer.from([
0x00, 0x1F // metadata_service_id + other flags
]);
var metadata_pointer_descriptor_program_number = Buffer.from([
((program_number & 0xFF00) >> 8), ((program_number & 0x00FF) >> 0)
]);
var metadata_descriptor_payload = Buffer.concat([
metadata_pointer_descriptor_application_format,
metadata_pointer_descriptor_application_format_identifier,
metadata_pointer_descriptor_format,
metadata_pointer_descriptor_format_identifier,
metadata_pointer_descriptor_flags,
metadata_pointer_descriptor_program_number,
]);
var metadata_descriptor_length = Buffer.from([metadata_descriptor_payload.length]);
var metadata_descriptor_tag = Buffer.from([0x26]);
return Buffer.concat([
metadata_descriptor_tag,
metadata_descriptor_length,
metadata_descriptor_payload,
]);
};
ID3.metadata_descriptor = function () {
var metadata_descriptor_application_format = Buffer.from([0xFF, 0xFF]);
var metadata_descriptor_application_format_identifier = Buffer.from([
0x49, 0x44, 0x33, 0x20, // ID3
]);
var metadata_descriptor_format = Buffer.from([0xFF]);
var metadata_descriptor_format_identifier = Buffer.from([
0x49, 0x44, 0x33, 0x20, // ID3
]);
var metadata_descriptor_flags = Buffer.from([
0xFF, 0x0F, // metadata_service_id + other flags
]);
var metadata_descriptor_payload = Buffer.concat([
metadata_descriptor_application_format,
metadata_descriptor_application_format_identifier,
metadata_descriptor_format,
metadata_descriptor_format_identifier,
metadata_descriptor_flags,
]);
var metadata_descriptor_length = Buffer.from([metadata_descriptor_payload.length]);
var metadata_descriptor_tag = Buffer.from([0x26]);
return Buffer.concat([
metadata_descriptor_tag,
metadata_descriptor_length,
metadata_descriptor_payload,
]);
};
ID3.metadata_elementary_stream = function (PID) {
var descriptor = this.metadata_descriptor();
var ES_info_length = Buffer.from([
((descriptor.length & 0xFF00) >> 8), ((descriptor.length & 0x00FF) >> 0),
]);
var elementary_PID = Buffer.from([
((PID & 0x1F00) >> 8), ((PID & 0x00FF) >> 0),
]);
var stream_type = Buffer.from([0x15]);
return Buffer.concat([
stream_type,
elementary_PID,
ES_info_length,
descriptor,
]);
};
ID3.ID3v2TXXX = function (description, text) {
var txxx_payload = Buffer.concat([
Buffer.from([0x03]),
Buffer.from(description, 'utf-8'),
Buffer.from([0x00]),
Buffer.from(text, 'utf-8'),
Buffer.from([0x00]), // for video.js TXXX handling (必ず NULL 終端にしておく方がいい、 NULL 終端前提の場合がある)
]);
var txxx_paylaod_size = Buffer.from([
((txxx_payload.length & 0xFE00000) >> 21),
((txxx_payload.length & 0x01FC000) >> 14),
((txxx_payload.length & 0x0003F80) >> 7),
((txxx_payload.length & 0x000007F) >> 0),
]);
var txxx_frame = Buffer.concat([
Buffer.from('TXXX', 'utf-8'),
txxx_paylaod_size,
Buffer.from([0x00, 0x00]),
txxx_payload,
]);
var txxx_frame_size = Buffer.from([
((txxx_frame.length & 0xFE00000) >> 21),
((txxx_frame.length & 0x01FC000) >> 14),
((txxx_frame.length & 0x0003F80) >> 7),
((txxx_frame.length & 0x000007F) >> 0),
]);
return Buffer.concat([
Buffer.from([0x49, 0x44, 0x33, 0x04, 0x00, 0x00]),
txxx_frame_size,
txxx_frame,
]);
};
ID3.ID3v2PRIV = function (owner, binary) {
var priv_payload = Buffer.concat([
Buffer.from(owner, 'utf-8'),
Buffer.from([0x00]),
binary
]);
var priv_paylaod_size = Buffer.from([
((priv_payload.length & 0xFE00000) >> 21),
((priv_payload.length & 0x01FC000) >> 14),
((priv_payload.length & 0x0003F80) >> 7),
((priv_payload.length & 0x000007F) >> 0),
]);
var priv_frame = Buffer.concat([
Buffer.from('PRIV', 'utf-8'),
priv_paylaod_size,
Buffer.from([0x00, 0x00]),
priv_payload,
]);
var priv_frame_size = Buffer.from([
((priv_frame.length & 0xFE00000) >> 21),
((priv_frame.length & 0x01FC000) >> 14),
((priv_frame.length & 0x0003F80) >> 7),
((priv_frame.length & 0x000007F) >> 0),
]);
return Buffer.concat([
Buffer.from([0x49, 0x44, 0x33, 0x04, 0x00, 0x00]),
priv_frame_size,
priv_frame,
]);
};
ID3.timedmetadata = function (pts, id3) {
var header = Buffer.from([
0x00, 0x00, 0x01, 0xbd, // +2 bytes
]);
var flags = Buffer.from([
0x84, 0x80, // (10, 00, 1, 0, 0, 0), (10 (PTS only), 0, 0, 0, 0, 0, 0, 0) +1 byte
]);
var PTS = Buffer.from([
((2 << 4) | (((pts / (1 << 30)) & 0x7) << 1) | 1),
((((pts >>> 0) & 0x3FC00000) >> 22)),
((((pts >>> 0) & 0x003F8000) >> 15) << 1) | 1,
((((pts >>> 0) & 0x00007F80) >> 7)),
((((pts >>> 0) & 0x0000007F) >> 0) << 1) | 1,
]);
// TSPES.PES_HEADER_SIZE + flags + PES_header_data_length + PTS + payload
var without_padding_length = arib_mpeg2ts_parser_2.TSPES.PES_HEADER_SIZE + 2 + 1 + 5 /* PTS */ + 5 /* padding for ffmepg metadata(0x15) handling*/ + id3.length;
var packet_payload_size = (arib_mpeg2ts_parser_1.TSPacket.PACKET_SIZE - arib_mpeg2ts_parser_1.TSPacket.HEADER_SIZE);
var stuffing_length = packet_payload_size - (without_padding_length % packet_payload_size);
var payload = Buffer.concat([
flags,
Buffer.from([5] /* PTS */),
PTS,
Buffer.alloc(5, 0),
/* ffmpeg は metadata (0x15) の先頭を 5byte をヘッダーだと思って、スキップしてデータ処理をする */
/* この 5byte のヘッダーは stream_id 0xbd ではなく、stream_id 0xfc の時にあるものなので、timed-id3 でスキップは不適格 */
/* なので、 ffmpeg じゃなく直で利用する場合には、この 5 byteパディングは要らない */
/* TODO: オプションで ffmpeg と正常ハンドリング と変えられるようにしておくこと */
id3,
]);
return Buffer.concat([
header,
Buffer.from([
(((payload.length + stuffing_length) & 0xFF00) >> 8), (((payload.length + stuffing_length) & 0x00FF) >> 0),
]),
payload,
Buffer.alloc(stuffing_length, 0xFF),
]);
};
return ID3;
}());
exports.default = ID3;