mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-03 09:49:28 +02:00
Update
This commit is contained in:
parent
0e3fa24329
commit
4e95a0e94c
369 changed files with 16946 additions and 89882 deletions
47
node_modules/mux.js/CHANGELOG.md
generated
vendored
47
node_modules/mux.js/CHANGELOG.md
generated
vendored
|
@ -1,3 +1,50 @@
|
|||
<a name="7.0.1"></a>
|
||||
## [7.0.1](https://github.com/videojs/mux.js/compare/v7.0.0...v7.0.1) (2023-10-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 708 captions multi-byte char fix ([#439](https://github.com/videojs/mux.js/issues/439)) ([ec31749](https://github.com/videojs/mux.js/commit/ec31749))
|
||||
|
||||
### Chores
|
||||
|
||||
* update v7.0.0 documentation ([#435](https://github.com/videojs/mux.js/issues/435)) ([21e55aa](https://github.com/videojs/mux.js/commit/21e55aa))
|
||||
|
||||
<a name="7.0.0"></a>
|
||||
# [7.0.0](https://github.com/videojs/mux.js/compare/v6.3.0...v7.0.0) (2023-07-21)
|
||||
|
||||
### Features
|
||||
|
||||
* add position data to captions ([#434](https://github.com/videojs/mux.js/issues/434)) ([30f2132](https://github.com/videojs/mux.js/commit/30f2132))
|
||||
|
||||
### Chores
|
||||
|
||||
* add npm publish step to the release workflow ([a8306cd](https://github.com/videojs/mux.js/commit/a8306cd))
|
||||
* rename workflow name from github-release to release and add discussion category name for github releases ([4ba1607](https://github.com/videojs/mux.js/commit/4ba1607))
|
||||
* Update CI and release workflows ([#431](https://github.com/videojs/mux.js/issues/431)) ([dc56f1b](https://github.com/videojs/mux.js/commit/dc56f1b))
|
||||
* update collaborator guide md ([51b3ed4](https://github.com/videojs/mux.js/commit/51b3ed4))
|
||||
* update git push suggestion in collaborator guide md ([73a5b60](https://github.com/videojs/mux.js/commit/73a5b60))
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* In the case of CEA-608 captions, mux.js will now be returning captions in the form of caption sets.
|
||||
This means that rather then returning a single text of combined caption cues, an array of caption cues is returned in the `content` property.
|
||||
|
||||
```js
|
||||
transmuxer.on('data', function (segment) {
|
||||
// create a VTTCue for all the parsed CEA-608 captions:>
|
||||
segment.captions.forEach(function(captionSet) {
|
||||
// Caption sets contains multiple captions with text and position data.
|
||||
captionSet.content.forEach(function(cue) {
|
||||
const newCue = new VTTCue(cue.startTime, cue.endTime, cue.text);
|
||||
newCue.line = cue.line;
|
||||
newCue.position = cue.position;
|
||||
|
||||
captionTextTrack.addCue(newCue);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
<a name="6.3.0"></a>
|
||||
# [6.3.0](https://github.com/videojs/mux.js/compare/v6.2.0...v6.3.0) (2023-02-22)
|
||||
|
||||
|
|
11
node_modules/mux.js/README.md
generated
vendored
11
node_modules/mux.js/README.md
generated
vendored
|
@ -333,8 +333,15 @@ transmuxer.on('data', function (segment) {
|
|||
metadataTextTrack.addCue(new VTTCue(time, time, frame.value));
|
||||
});
|
||||
// create a VTTCue for all the parsed CEA-608 captions:>
|
||||
segment.captions.forEach(function(cue) {
|
||||
captionTextTrack.addCue(new VTTCue(cue.startTime, cue.endTime, cue.text));
|
||||
segment.captions.forEach(function(captionSet) {
|
||||
// Caption sets contains multiple caption cues with text and position data.
|
||||
captionSet.content.forEach(function(cue) {
|
||||
const newCue = new VTTCue(cue.startTime, cue.endTime, cue.text);
|
||||
newCue.line = cue.line;
|
||||
newCue.position = cue.position;
|
||||
|
||||
captionTextTrack.addCue(newCue);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
|
2
node_modules/mux.js/cjs/flv/coalesce-stream.js
generated
vendored
2
node_modules/mux.js/cjs/flv/coalesce-stream.js
generated
vendored
|
@ -33,7 +33,7 @@ var CoalesceStream = function CoalesceStream(options) {
|
|||
this.push = function (output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
} // buffer incoming id3 tags until the final flush
|
||||
|
||||
|
|
154
node_modules/mux.js/cjs/m2ts/caption-stream.js
generated
vendored
154
node_modules/mux.js/cjs/m2ts/caption-stream.js
generated
vendored
|
@ -707,19 +707,35 @@ Cea708Stream.prototype.handleText = function (i, service, options) {
|
|||
var nextByte = packetData[i + 1];
|
||||
var win = service.currentWindow;
|
||||
var char;
|
||||
var charCodeArray; // Use the TextDecoder if one was created for this service
|
||||
var charCodeArray; // Converts an array of bytes to a unicode hex string.
|
||||
|
||||
function toHexString(byteArray) {
|
||||
return byteArray.map(function (byte) {
|
||||
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
} // Use the TextDecoder if one was created for this service
|
||||
|
||||
|
||||
if (service.textDecoder_ && !isExtended) {
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
}
|
||||
|
||||
char = service.textDecoder_.decode(new Uint8Array(charCodeArray));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
// We assume any multi-byte char without a decoder is unicode.
|
||||
if (isMultiByte) {
|
||||
var unicode = toHexString(charCodeArray); // Takes a unicode hex string and creates a single character.
|
||||
|
||||
char = String.fromCharCode(parseInt(unicode, 16));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
}
|
||||
}
|
||||
|
||||
if (win.pendingNewLine && !win.isEmpty()) {
|
||||
|
@ -1364,13 +1380,19 @@ var BOTTOM_ROW = 14; // This array is used for mapping PACs -> row #, since ther
|
|||
|
||||
var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620, 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420]; // CEA-608 captions are rendered onto a 34x15 matrix of character
|
||||
// cells. The "bottom" row is the last element in the outer array.
|
||||
// We keep track of positioning information as we go by storing the
|
||||
// number of indentations and the tab offset in this buffer.
|
||||
|
||||
var createDisplayBuffer = function createDisplayBuffer() {
|
||||
var result = [],
|
||||
i = BOTTOM_ROW + 1;
|
||||
|
||||
while (i--) {
|
||||
result.push('');
|
||||
result.push({
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1439,9 +1461,9 @@ var Cea608Stream = function Cea608Stream(field, dataChannel) {
|
|||
this.startPts_ = packet.pts;
|
||||
} else if (data === this.BACKSPACE_) {
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
}
|
||||
} else if (data === this.ERASE_DISPLAYED_MEMORY_) {
|
||||
this.flushDisplayed(packet.pts);
|
||||
|
@ -1474,9 +1496,9 @@ var Cea608Stream = function Cea608Stream(field, dataChannel) {
|
|||
// backspace the "e" and insert "è".
|
||||
// Delete the previous character
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
} // Bitmask char0 so that we can apply character transformations
|
||||
// regardless of field and data channel.
|
||||
// Then byte-shift to the left and OR with char1 so we can pass the
|
||||
|
@ -1508,7 +1530,11 @@ var Cea608Stream = function Cea608Stream(field, dataChannel) {
|
|||
// increments, with an additional offset code of 1-3 to reach any
|
||||
// of the 32 columns specified by CEA-608. So all we need to do
|
||||
// here is increment the column cursor by the given offset.
|
||||
this.column_ += char1 & 0x03; // Detect PACs (Preamble Address Codes)
|
||||
var offset = char1 & 0x03; // For an offest value 1-3, set the offset for that caption
|
||||
// in the non-displayed array.
|
||||
|
||||
this.nonDisplayed_[this.row_].offset = offset;
|
||||
this.column_ += offset; // Detect PACs (Preamble Address Codes)
|
||||
} else if (this.isPAC(char0, char1)) {
|
||||
// There's no logic for PAC -> row mapping, so we have to just
|
||||
// find the row code in an array and use its index :(
|
||||
|
@ -1542,7 +1568,10 @@ var Cea608Stream = function Cea608Stream(field, dataChannel) {
|
|||
// increments the column cursor by 4, so we can get the desired
|
||||
// column position by bit-shifting to the right (to get n/2)
|
||||
// and multiplying by 4.
|
||||
this.column_ = ((data & 0xe) >> 1) * 4;
|
||||
var indentations = (data & 0xe) >> 1;
|
||||
this.column_ = indentations * 4; // add to the number of indentations for positioning
|
||||
|
||||
this.nonDisplayed_[this.row_].indent += indentations;
|
||||
}
|
||||
|
||||
if (this.isColorPAC(char1)) {
|
||||
|
@ -1573,29 +1602,52 @@ Cea608Stream.prototype = new Stream(); // Trigger a cue point that captures the
|
|||
// display buffer
|
||||
|
||||
Cea608Stream.prototype.flushDisplayed = function (pts) {
|
||||
var content = this.displayed_ // remove spaces from the start and end of the string
|
||||
.map(function (row, index) {
|
||||
try {
|
||||
return row.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
return '';
|
||||
var _this = this;
|
||||
|
||||
var logWarning = function logWarning(index) {
|
||||
_this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
};
|
||||
|
||||
var content = [];
|
||||
this.displayed_.forEach(function (row, i) {
|
||||
if (row && row.text && row.text.length) {
|
||||
try {
|
||||
// remove spaces from the start and end of the string
|
||||
row.text = row.text.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
logWarning(i);
|
||||
} // See the below link for more details on the following fields:
|
||||
// https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608
|
||||
|
||||
|
||||
if (row.text.length) {
|
||||
content.push({
|
||||
// The text to be displayed in the caption from this specific row, with whitespace removed.
|
||||
text: row.text,
|
||||
// Value between 1 and 15 representing the PAC row used to calculate line height.
|
||||
line: i + 1,
|
||||
// A number representing the indent position by percentage (CEA-608 PAC indent code).
|
||||
// The value will be a number between 10 and 80. Offset is used to add an aditional
|
||||
// value to the position if necessary.
|
||||
position: 10 + Math.min(70, row.indent * 10) + row.offset * 2.5
|
||||
});
|
||||
}
|
||||
} else if (row === undefined || row === null) {
|
||||
logWarning(i);
|
||||
}
|
||||
}, this) // combine all text rows to display in one cue
|
||||
.join('\n') // and remove blank rows from the start and end, but not the middle
|
||||
.replace(/^\n+|\n+$/g, '');
|
||||
});
|
||||
|
||||
if (content.length) {
|
||||
this.trigger('data', {
|
||||
startPts: this.startPts_,
|
||||
endPts: pts,
|
||||
text: content,
|
||||
content: content,
|
||||
stream: this.name_
|
||||
});
|
||||
}
|
||||
|
@ -1804,7 +1856,11 @@ Cea608Stream.prototype.setRollUp = function (pts, newBaseRow) {
|
|||
// move currently displayed captions (up or down) to the new base row
|
||||
for (var i = 0; i < this.rollUpRows_; i++) {
|
||||
this.displayed_[newBaseRow - i] = this.displayed_[this.row_ - i];
|
||||
this.displayed_[this.row_ - i] = '';
|
||||
this.displayed_[this.row_ - i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1841,27 +1897,35 @@ Cea608Stream.prototype.clearFormatting = function (pts) {
|
|||
|
||||
|
||||
Cea608Stream.prototype.popOn = function (pts, text) {
|
||||
var baseRow = this.nonDisplayed_[this.row_]; // buffer characters
|
||||
var baseRow = this.nonDisplayed_[this.row_].text; // buffer characters
|
||||
|
||||
baseRow += text;
|
||||
this.nonDisplayed_[this.row_] = baseRow;
|
||||
this.nonDisplayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.rollUp = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.shiftRowsUp_ = function () {
|
||||
var i; // clear out inactive rows
|
||||
|
||||
for (i = 0; i < this.topRow_; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
|
||||
for (i = this.row_ + 1; i < BOTTOM_ROW + 1; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
} // shift displayed rows up
|
||||
|
||||
|
||||
|
@ -1870,13 +1934,17 @@ Cea608Stream.prototype.shiftRowsUp_ = function () {
|
|||
} // clear out the bottom row
|
||||
|
||||
|
||||
this.displayed_[this.row_] = '';
|
||||
this.displayed_[this.row_] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.paintOn = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
}; // exports
|
||||
|
||||
|
||||
|
|
5
node_modules/mux.js/cjs/mp4/caption-parser.js
generated
vendored
5
node_modules/mux.js/cjs/mp4/caption-parser.js
generated
vendored
|
@ -248,7 +248,10 @@ var parseCaptionNals = function parseCaptionNals(segment, videoTrackId) {
|
|||
* @return {?Object[]} parsedCaptions - A list of captions or null if no video tracks
|
||||
* @return {Number} parsedCaptions[].startTime - The time to show the caption in seconds
|
||||
* @return {Number} parsedCaptions[].endTime - The time to stop showing the caption in seconds
|
||||
* @return {String} parsedCaptions[].text - The visible content of the caption
|
||||
* @return {Object[]} parsedCaptions[].content - A list of individual caption segments
|
||||
* @return {String} parsedCaptions[].content.text - The visible content of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.line - The line height from 1-15 for positioning of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.position - The column indent percentage for cue positioning from 10-80
|
||||
**/
|
||||
|
||||
|
||||
|
|
2
node_modules/mux.js/cjs/mp4/transmuxer.js
generated
vendored
2
node_modules/mux.js/cjs/mp4/transmuxer.js
generated
vendored
|
@ -654,7 +654,7 @@ _CoalesceStream = function CoalesceStream(options, metadataStream) {
|
|||
this.push = function (output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
} // buffer incoming id3 tags until the final flush
|
||||
|
||||
|
|
156
node_modules/mux.js/dist/mux-flv.js
generated
vendored
156
node_modules/mux.js/dist/mux-flv.js
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
/*! @name mux.js @version 6.3.0 @license Apache-2.0 */
|
||||
/*! @name mux.js @version 7.0.1 @license Apache-2.0 */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
|
@ -1407,19 +1407,33 @@
|
|||
var nextByte = packetData[i + 1];
|
||||
var win = service.currentWindow;
|
||||
var char;
|
||||
var charCodeArray; // Use the TextDecoder if one was created for this service
|
||||
var charCodeArray; // Converts an array of bytes to a unicode hex string.
|
||||
|
||||
function toHexString(byteArray) {
|
||||
return byteArray.map(function (byte) {
|
||||
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
} // Use the TextDecoder if one was created for this service
|
||||
|
||||
|
||||
if (service.textDecoder_ && !isExtended) {
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
}
|
||||
|
||||
char = service.textDecoder_.decode(new Uint8Array(charCodeArray));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
// We assume any multi-byte char without a decoder is unicode.
|
||||
if (isMultiByte) {
|
||||
var unicode = toHexString(charCodeArray); // Takes a unicode hex string and creates a single character.
|
||||
|
||||
char = String.fromCharCode(parseInt(unicode, 16));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
}
|
||||
}
|
||||
|
||||
if (win.pendingNewLine && !win.isEmpty()) {
|
||||
|
@ -2063,13 +2077,19 @@
|
|||
|
||||
var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620, 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420]; // CEA-608 captions are rendered onto a 34x15 matrix of character
|
||||
// cells. The "bottom" row is the last element in the outer array.
|
||||
// We keep track of positioning information as we go by storing the
|
||||
// number of indentations and the tab offset in this buffer.
|
||||
|
||||
var createDisplayBuffer = function createDisplayBuffer() {
|
||||
var result = [],
|
||||
i = BOTTOM_ROW + 1;
|
||||
|
||||
while (i--) {
|
||||
result.push('');
|
||||
result.push({
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -2138,9 +2158,9 @@
|
|||
this.startPts_ = packet.pts;
|
||||
} else if (data === this.BACKSPACE_) {
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
}
|
||||
} else if (data === this.ERASE_DISPLAYED_MEMORY_) {
|
||||
this.flushDisplayed(packet.pts);
|
||||
|
@ -2173,9 +2193,9 @@
|
|||
// backspace the "e" and insert "è".
|
||||
// Delete the previous character
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
} // Bitmask char0 so that we can apply character transformations
|
||||
// regardless of field and data channel.
|
||||
// Then byte-shift to the left and OR with char1 so we can pass the
|
||||
|
@ -2207,7 +2227,11 @@
|
|||
// increments, with an additional offset code of 1-3 to reach any
|
||||
// of the 32 columns specified by CEA-608. So all we need to do
|
||||
// here is increment the column cursor by the given offset.
|
||||
this.column_ += char1 & 0x03; // Detect PACs (Preamble Address Codes)
|
||||
var offset = char1 & 0x03; // For an offest value 1-3, set the offset for that caption
|
||||
// in the non-displayed array.
|
||||
|
||||
this.nonDisplayed_[this.row_].offset = offset;
|
||||
this.column_ += offset; // Detect PACs (Preamble Address Codes)
|
||||
} else if (this.isPAC(char0, char1)) {
|
||||
// There's no logic for PAC -> row mapping, so we have to just
|
||||
// find the row code in an array and use its index :(
|
||||
|
@ -2241,7 +2265,10 @@
|
|||
// increments the column cursor by 4, so we can get the desired
|
||||
// column position by bit-shifting to the right (to get n/2)
|
||||
// and multiplying by 4.
|
||||
this.column_ = ((data & 0xe) >> 1) * 4;
|
||||
var indentations = (data & 0xe) >> 1;
|
||||
this.column_ = indentations * 4; // add to the number of indentations for positioning
|
||||
|
||||
this.nonDisplayed_[this.row_].indent += indentations;
|
||||
}
|
||||
|
||||
if (this.isColorPAC(char1)) {
|
||||
|
@ -2272,29 +2299,52 @@
|
|||
// display buffer
|
||||
|
||||
Cea608Stream.prototype.flushDisplayed = function (pts) {
|
||||
var content = this.displayed_ // remove spaces from the start and end of the string
|
||||
.map(function (row, index) {
|
||||
try {
|
||||
return row.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
return '';
|
||||
var _this = this;
|
||||
|
||||
var logWarning = function logWarning(index) {
|
||||
_this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
};
|
||||
|
||||
var content = [];
|
||||
this.displayed_.forEach(function (row, i) {
|
||||
if (row && row.text && row.text.length) {
|
||||
try {
|
||||
// remove spaces from the start and end of the string
|
||||
row.text = row.text.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
logWarning(i);
|
||||
} // See the below link for more details on the following fields:
|
||||
// https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608
|
||||
|
||||
|
||||
if (row.text.length) {
|
||||
content.push({
|
||||
// The text to be displayed in the caption from this specific row, with whitespace removed.
|
||||
text: row.text,
|
||||
// Value between 1 and 15 representing the PAC row used to calculate line height.
|
||||
line: i + 1,
|
||||
// A number representing the indent position by percentage (CEA-608 PAC indent code).
|
||||
// The value will be a number between 10 and 80. Offset is used to add an aditional
|
||||
// value to the position if necessary.
|
||||
position: 10 + Math.min(70, row.indent * 10) + row.offset * 2.5
|
||||
});
|
||||
}
|
||||
} else if (row === undefined || row === null) {
|
||||
logWarning(i);
|
||||
}
|
||||
}, this) // combine all text rows to display in one cue
|
||||
.join('\n') // and remove blank rows from the start and end, but not the middle
|
||||
.replace(/^\n+|\n+$/g, '');
|
||||
});
|
||||
|
||||
if (content.length) {
|
||||
this.trigger('data', {
|
||||
startPts: this.startPts_,
|
||||
endPts: pts,
|
||||
text: content,
|
||||
content: content,
|
||||
stream: this.name_
|
||||
});
|
||||
}
|
||||
|
@ -2503,7 +2553,11 @@
|
|||
// move currently displayed captions (up or down) to the new base row
|
||||
for (var i = 0; i < this.rollUpRows_; i++) {
|
||||
this.displayed_[newBaseRow - i] = this.displayed_[this.row_ - i];
|
||||
this.displayed_[this.row_ - i] = '';
|
||||
this.displayed_[this.row_ - i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2540,27 +2594,35 @@
|
|||
|
||||
|
||||
Cea608Stream.prototype.popOn = function (pts, text) {
|
||||
var baseRow = this.nonDisplayed_[this.row_]; // buffer characters
|
||||
var baseRow = this.nonDisplayed_[this.row_].text; // buffer characters
|
||||
|
||||
baseRow += text;
|
||||
this.nonDisplayed_[this.row_] = baseRow;
|
||||
this.nonDisplayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.rollUp = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.shiftRowsUp_ = function () {
|
||||
var i; // clear out inactive rows
|
||||
|
||||
for (i = 0; i < this.topRow_; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
|
||||
for (i = this.row_ + 1; i < BOTTOM_ROW + 1; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
} // shift displayed rows up
|
||||
|
||||
|
||||
|
@ -2569,13 +2631,17 @@
|
|||
} // clear out the bottom row
|
||||
|
||||
|
||||
this.displayed_[this.row_] = '';
|
||||
this.displayed_[this.row_] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.paintOn = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
}; // exports
|
||||
|
||||
|
||||
|
@ -4591,7 +4657,7 @@
|
|||
this.push = function (output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
} // buffer incoming id3 tags until the final flush
|
||||
|
||||
|
|
4
node_modules/mux.js/dist/mux-flv.min.js
generated
vendored
4
node_modules/mux.js/dist/mux-flv.min.js
generated
vendored
File diff suppressed because one or more lines are too long
161
node_modules/mux.js/dist/mux-mp4.js
generated
vendored
161
node_modules/mux.js/dist/mux-mp4.js
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
/*! @name mux.js @version 6.3.0 @license Apache-2.0 */
|
||||
/*! @name mux.js @version 7.0.1 @license Apache-2.0 */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('global/window')) :
|
||||
typeof define === 'function' && define.amd ? define(['global/window'], factory) :
|
||||
|
@ -3339,19 +3339,33 @@
|
|||
var nextByte = packetData[i + 1];
|
||||
var win = service.currentWindow;
|
||||
var char;
|
||||
var charCodeArray; // Use the TextDecoder if one was created for this service
|
||||
var charCodeArray; // Converts an array of bytes to a unicode hex string.
|
||||
|
||||
function toHexString(byteArray) {
|
||||
return byteArray.map(function (byte) {
|
||||
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
} // Use the TextDecoder if one was created for this service
|
||||
|
||||
|
||||
if (service.textDecoder_ && !isExtended) {
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
}
|
||||
|
||||
char = service.textDecoder_.decode(new Uint8Array(charCodeArray));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
// We assume any multi-byte char without a decoder is unicode.
|
||||
if (isMultiByte) {
|
||||
var unicode = toHexString(charCodeArray); // Takes a unicode hex string and creates a single character.
|
||||
|
||||
char = String.fromCharCode(parseInt(unicode, 16));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
}
|
||||
}
|
||||
|
||||
if (win.pendingNewLine && !win.isEmpty()) {
|
||||
|
@ -3995,13 +4009,19 @@
|
|||
|
||||
var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620, 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420]; // CEA-608 captions are rendered onto a 34x15 matrix of character
|
||||
// cells. The "bottom" row is the last element in the outer array.
|
||||
// We keep track of positioning information as we go by storing the
|
||||
// number of indentations and the tab offset in this buffer.
|
||||
|
||||
var createDisplayBuffer = function createDisplayBuffer() {
|
||||
var result = [],
|
||||
i = BOTTOM_ROW + 1;
|
||||
|
||||
while (i--) {
|
||||
result.push('');
|
||||
result.push({
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -4070,9 +4090,9 @@
|
|||
this.startPts_ = packet.pts;
|
||||
} else if (data === this.BACKSPACE_) {
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
}
|
||||
} else if (data === this.ERASE_DISPLAYED_MEMORY_) {
|
||||
this.flushDisplayed(packet.pts);
|
||||
|
@ -4105,9 +4125,9 @@
|
|||
// backspace the "e" and insert "è".
|
||||
// Delete the previous character
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
} // Bitmask char0 so that we can apply character transformations
|
||||
// regardless of field and data channel.
|
||||
// Then byte-shift to the left and OR with char1 so we can pass the
|
||||
|
@ -4139,7 +4159,11 @@
|
|||
// increments, with an additional offset code of 1-3 to reach any
|
||||
// of the 32 columns specified by CEA-608. So all we need to do
|
||||
// here is increment the column cursor by the given offset.
|
||||
this.column_ += char1 & 0x03; // Detect PACs (Preamble Address Codes)
|
||||
var offset = char1 & 0x03; // For an offest value 1-3, set the offset for that caption
|
||||
// in the non-displayed array.
|
||||
|
||||
this.nonDisplayed_[this.row_].offset = offset;
|
||||
this.column_ += offset; // Detect PACs (Preamble Address Codes)
|
||||
} else if (this.isPAC(char0, char1)) {
|
||||
// There's no logic for PAC -> row mapping, so we have to just
|
||||
// find the row code in an array and use its index :(
|
||||
|
@ -4173,7 +4197,10 @@
|
|||
// increments the column cursor by 4, so we can get the desired
|
||||
// column position by bit-shifting to the right (to get n/2)
|
||||
// and multiplying by 4.
|
||||
this.column_ = ((data & 0xe) >> 1) * 4;
|
||||
var indentations = (data & 0xe) >> 1;
|
||||
this.column_ = indentations * 4; // add to the number of indentations for positioning
|
||||
|
||||
this.nonDisplayed_[this.row_].indent += indentations;
|
||||
}
|
||||
|
||||
if (this.isColorPAC(char1)) {
|
||||
|
@ -4204,29 +4231,52 @@
|
|||
// display buffer
|
||||
|
||||
Cea608Stream.prototype.flushDisplayed = function (pts) {
|
||||
var content = this.displayed_ // remove spaces from the start and end of the string
|
||||
.map(function (row, index) {
|
||||
try {
|
||||
return row.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
return '';
|
||||
var _this = this;
|
||||
|
||||
var logWarning = function logWarning(index) {
|
||||
_this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
};
|
||||
|
||||
var content = [];
|
||||
this.displayed_.forEach(function (row, i) {
|
||||
if (row && row.text && row.text.length) {
|
||||
try {
|
||||
// remove spaces from the start and end of the string
|
||||
row.text = row.text.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
logWarning(i);
|
||||
} // See the below link for more details on the following fields:
|
||||
// https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608
|
||||
|
||||
|
||||
if (row.text.length) {
|
||||
content.push({
|
||||
// The text to be displayed in the caption from this specific row, with whitespace removed.
|
||||
text: row.text,
|
||||
// Value between 1 and 15 representing the PAC row used to calculate line height.
|
||||
line: i + 1,
|
||||
// A number representing the indent position by percentage (CEA-608 PAC indent code).
|
||||
// The value will be a number between 10 and 80. Offset is used to add an aditional
|
||||
// value to the position if necessary.
|
||||
position: 10 + Math.min(70, row.indent * 10) + row.offset * 2.5
|
||||
});
|
||||
}
|
||||
} else if (row === undefined || row === null) {
|
||||
logWarning(i);
|
||||
}
|
||||
}, this) // combine all text rows to display in one cue
|
||||
.join('\n') // and remove blank rows from the start and end, but not the middle
|
||||
.replace(/^\n+|\n+$/g, '');
|
||||
});
|
||||
|
||||
if (content.length) {
|
||||
this.trigger('data', {
|
||||
startPts: this.startPts_,
|
||||
endPts: pts,
|
||||
text: content,
|
||||
content: content,
|
||||
stream: this.name_
|
||||
});
|
||||
}
|
||||
|
@ -4435,7 +4485,11 @@
|
|||
// move currently displayed captions (up or down) to the new base row
|
||||
for (var i = 0; i < this.rollUpRows_; i++) {
|
||||
this.displayed_[newBaseRow - i] = this.displayed_[this.row_ - i];
|
||||
this.displayed_[this.row_ - i] = '';
|
||||
this.displayed_[this.row_ - i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4472,27 +4526,35 @@
|
|||
|
||||
|
||||
Cea608Stream.prototype.popOn = function (pts, text) {
|
||||
var baseRow = this.nonDisplayed_[this.row_]; // buffer characters
|
||||
var baseRow = this.nonDisplayed_[this.row_].text; // buffer characters
|
||||
|
||||
baseRow += text;
|
||||
this.nonDisplayed_[this.row_] = baseRow;
|
||||
this.nonDisplayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.rollUp = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.shiftRowsUp_ = function () {
|
||||
var i; // clear out inactive rows
|
||||
|
||||
for (i = 0; i < this.topRow_; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
|
||||
for (i = this.row_ + 1; i < BOTTOM_ROW + 1; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
} // shift displayed rows up
|
||||
|
||||
|
||||
|
@ -4501,13 +4563,17 @@
|
|||
} // clear out the bottom row
|
||||
|
||||
|
||||
this.displayed_[this.row_] = '';
|
||||
this.displayed_[this.row_] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.paintOn = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
}; // exports
|
||||
|
||||
|
||||
|
@ -7077,7 +7143,7 @@
|
|||
this.push = function (output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
} // buffer incoming id3 tags until the final flush
|
||||
|
||||
|
@ -7758,7 +7824,10 @@
|
|||
* @return {?Object[]} parsedCaptions - A list of captions or null if no video tracks
|
||||
* @return {Number} parsedCaptions[].startTime - The time to show the caption in seconds
|
||||
* @return {Number} parsedCaptions[].endTime - The time to stop showing the caption in seconds
|
||||
* @return {String} parsedCaptions[].text - The visible content of the caption
|
||||
* @return {Object[]} parsedCaptions[].content - A list of individual caption segments
|
||||
* @return {String} parsedCaptions[].content.text - The visible content of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.line - The line height from 1-15 for positioning of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.position - The column indent percentage for cue positioning from 10-80
|
||||
**/
|
||||
|
||||
|
||||
|
|
4
node_modules/mux.js/dist/mux-mp4.min.js
generated
vendored
4
node_modules/mux.js/dist/mux-mp4.min.js
generated
vendored
File diff suppressed because one or more lines are too long
163
node_modules/mux.js/dist/mux.js
generated
vendored
163
node_modules/mux.js/dist/mux.js
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
/*! @name mux.js @version 6.3.0 @license Apache-2.0 */
|
||||
/*! @name mux.js @version 7.0.1 @license Apache-2.0 */
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('global/window')) :
|
||||
typeof define === 'function' && define.amd ? define(['global/window'], factory) :
|
||||
|
@ -4200,19 +4200,33 @@
|
|||
var nextByte = packetData[i + 1];
|
||||
var win = service.currentWindow;
|
||||
var char;
|
||||
var charCodeArray; // Use the TextDecoder if one was created for this service
|
||||
var charCodeArray; // Converts an array of bytes to a unicode hex string.
|
||||
|
||||
function toHexString(byteArray) {
|
||||
return byteArray.map(function (byte) {
|
||||
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
} // Use the TextDecoder if one was created for this service
|
||||
|
||||
|
||||
if (service.textDecoder_ && !isExtended) {
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
}
|
||||
|
||||
char = service.textDecoder_.decode(new Uint8Array(charCodeArray));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
// We assume any multi-byte char without a decoder is unicode.
|
||||
if (isMultiByte) {
|
||||
var unicode = toHexString(charCodeArray); // Takes a unicode hex string and creates a single character.
|
||||
|
||||
char = String.fromCharCode(parseInt(unicode, 16));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
}
|
||||
}
|
||||
|
||||
if (win.pendingNewLine && !win.isEmpty()) {
|
||||
|
@ -4856,13 +4870,19 @@
|
|||
|
||||
var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620, 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420]; // CEA-608 captions are rendered onto a 34x15 matrix of character
|
||||
// cells. The "bottom" row is the last element in the outer array.
|
||||
// We keep track of positioning information as we go by storing the
|
||||
// number of indentations and the tab offset in this buffer.
|
||||
|
||||
var createDisplayBuffer = function createDisplayBuffer() {
|
||||
var result = [],
|
||||
i = BOTTOM_ROW + 1;
|
||||
|
||||
while (i--) {
|
||||
result.push('');
|
||||
result.push({
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -4931,9 +4951,9 @@
|
|||
this.startPts_ = packet.pts;
|
||||
} else if (data === this.BACKSPACE_) {
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
}
|
||||
} else if (data === this.ERASE_DISPLAYED_MEMORY_) {
|
||||
this.flushDisplayed(packet.pts);
|
||||
|
@ -4966,9 +4986,9 @@
|
|||
// backspace the "e" and insert "è".
|
||||
// Delete the previous character
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
} // Bitmask char0 so that we can apply character transformations
|
||||
// regardless of field and data channel.
|
||||
// Then byte-shift to the left and OR with char1 so we can pass the
|
||||
|
@ -5000,7 +5020,11 @@
|
|||
// increments, with an additional offset code of 1-3 to reach any
|
||||
// of the 32 columns specified by CEA-608. So all we need to do
|
||||
// here is increment the column cursor by the given offset.
|
||||
this.column_ += char1 & 0x03; // Detect PACs (Preamble Address Codes)
|
||||
var offset = char1 & 0x03; // For an offest value 1-3, set the offset for that caption
|
||||
// in the non-displayed array.
|
||||
|
||||
this.nonDisplayed_[this.row_].offset = offset;
|
||||
this.column_ += offset; // Detect PACs (Preamble Address Codes)
|
||||
} else if (this.isPAC(char0, char1)) {
|
||||
// There's no logic for PAC -> row mapping, so we have to just
|
||||
// find the row code in an array and use its index :(
|
||||
|
@ -5034,7 +5058,10 @@
|
|||
// increments the column cursor by 4, so we can get the desired
|
||||
// column position by bit-shifting to the right (to get n/2)
|
||||
// and multiplying by 4.
|
||||
this.column_ = ((data & 0xe) >> 1) * 4;
|
||||
var indentations = (data & 0xe) >> 1;
|
||||
this.column_ = indentations * 4; // add to the number of indentations for positioning
|
||||
|
||||
this.nonDisplayed_[this.row_].indent += indentations;
|
||||
}
|
||||
|
||||
if (this.isColorPAC(char1)) {
|
||||
|
@ -5065,29 +5092,52 @@
|
|||
// display buffer
|
||||
|
||||
Cea608Stream.prototype.flushDisplayed = function (pts) {
|
||||
var content = this.displayed_ // remove spaces from the start and end of the string
|
||||
.map(function (row, index) {
|
||||
try {
|
||||
return row.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
return '';
|
||||
var _this = this;
|
||||
|
||||
var logWarning = function logWarning(index) {
|
||||
_this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
};
|
||||
|
||||
var content = [];
|
||||
this.displayed_.forEach(function (row, i) {
|
||||
if (row && row.text && row.text.length) {
|
||||
try {
|
||||
// remove spaces from the start and end of the string
|
||||
row.text = row.text.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
logWarning(i);
|
||||
} // See the below link for more details on the following fields:
|
||||
// https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608
|
||||
|
||||
|
||||
if (row.text.length) {
|
||||
content.push({
|
||||
// The text to be displayed in the caption from this specific row, with whitespace removed.
|
||||
text: row.text,
|
||||
// Value between 1 and 15 representing the PAC row used to calculate line height.
|
||||
line: i + 1,
|
||||
// A number representing the indent position by percentage (CEA-608 PAC indent code).
|
||||
// The value will be a number between 10 and 80. Offset is used to add an aditional
|
||||
// value to the position if necessary.
|
||||
position: 10 + Math.min(70, row.indent * 10) + row.offset * 2.5
|
||||
});
|
||||
}
|
||||
} else if (row === undefined || row === null) {
|
||||
logWarning(i);
|
||||
}
|
||||
}, this) // combine all text rows to display in one cue
|
||||
.join('\n') // and remove blank rows from the start and end, but not the middle
|
||||
.replace(/^\n+|\n+$/g, '');
|
||||
});
|
||||
|
||||
if (content.length) {
|
||||
this.trigger('data', {
|
||||
startPts: this.startPts_,
|
||||
endPts: pts,
|
||||
text: content,
|
||||
content: content,
|
||||
stream: this.name_
|
||||
});
|
||||
}
|
||||
|
@ -5296,7 +5346,11 @@
|
|||
// move currently displayed captions (up or down) to the new base row
|
||||
for (var i = 0; i < this.rollUpRows_; i++) {
|
||||
this.displayed_[newBaseRow - i] = this.displayed_[this.row_ - i];
|
||||
this.displayed_[this.row_ - i] = '';
|
||||
this.displayed_[this.row_ - i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5333,27 +5387,35 @@
|
|||
|
||||
|
||||
Cea608Stream.prototype.popOn = function (pts, text) {
|
||||
var baseRow = this.nonDisplayed_[this.row_]; // buffer characters
|
||||
var baseRow = this.nonDisplayed_[this.row_].text; // buffer characters
|
||||
|
||||
baseRow += text;
|
||||
this.nonDisplayed_[this.row_] = baseRow;
|
||||
this.nonDisplayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.rollUp = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.shiftRowsUp_ = function () {
|
||||
var i; // clear out inactive rows
|
||||
|
||||
for (i = 0; i < this.topRow_; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
|
||||
for (i = this.row_ + 1; i < BOTTOM_ROW + 1; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
} // shift displayed rows up
|
||||
|
||||
|
||||
|
@ -5362,13 +5424,17 @@
|
|||
} // clear out the bottom row
|
||||
|
||||
|
||||
this.displayed_[this.row_] = '';
|
||||
this.displayed_[this.row_] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.paintOn = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
}; // exports
|
||||
|
||||
|
||||
|
@ -7089,7 +7155,7 @@
|
|||
this.push = function (output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
} // buffer incoming id3 tags until the final flush
|
||||
|
||||
|
@ -7770,7 +7836,10 @@
|
|||
* @return {?Object[]} parsedCaptions - A list of captions or null if no video tracks
|
||||
* @return {Number} parsedCaptions[].startTime - The time to show the caption in seconds
|
||||
* @return {Number} parsedCaptions[].endTime - The time to stop showing the caption in seconds
|
||||
* @return {String} parsedCaptions[].text - The visible content of the caption
|
||||
* @return {Object[]} parsedCaptions[].content - A list of individual caption segments
|
||||
* @return {String} parsedCaptions[].content.text - The visible content of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.line - The line height from 1-15 for positioning of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.position - The column indent percentage for cue positioning from 10-80
|
||||
**/
|
||||
|
||||
|
||||
|
@ -8422,7 +8491,7 @@
|
|||
this.push = function (output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
} // buffer incoming id3 tags until the final flush
|
||||
|
||||
|
|
4
node_modules/mux.js/dist/mux.min.js
generated
vendored
4
node_modules/mux.js/dist/mux.min.js
generated
vendored
File diff suppressed because one or more lines are too long
2
node_modules/mux.js/es/flv/coalesce-stream.js
generated
vendored
2
node_modules/mux.js/es/flv/coalesce-stream.js
generated
vendored
|
@ -33,7 +33,7 @@ var CoalesceStream = function CoalesceStream(options) {
|
|||
this.push = function (output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
} // buffer incoming id3 tags until the final flush
|
||||
|
||||
|
|
154
node_modules/mux.js/es/m2ts/caption-stream.js
generated
vendored
154
node_modules/mux.js/es/m2ts/caption-stream.js
generated
vendored
|
@ -707,19 +707,35 @@ Cea708Stream.prototype.handleText = function (i, service, options) {
|
|||
var nextByte = packetData[i + 1];
|
||||
var win = service.currentWindow;
|
||||
var char;
|
||||
var charCodeArray; // Use the TextDecoder if one was created for this service
|
||||
var charCodeArray; // Converts an array of bytes to a unicode hex string.
|
||||
|
||||
function toHexString(byteArray) {
|
||||
return byteArray.map(function (byte) {
|
||||
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
} // Use the TextDecoder if one was created for this service
|
||||
|
||||
|
||||
if (service.textDecoder_ && !isExtended) {
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
}
|
||||
|
||||
char = service.textDecoder_.decode(new Uint8Array(charCodeArray));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
// We assume any multi-byte char without a decoder is unicode.
|
||||
if (isMultiByte) {
|
||||
var unicode = toHexString(charCodeArray); // Takes a unicode hex string and creates a single character.
|
||||
|
||||
char = String.fromCharCode(parseInt(unicode, 16));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
}
|
||||
}
|
||||
|
||||
if (win.pendingNewLine && !win.isEmpty()) {
|
||||
|
@ -1364,13 +1380,19 @@ var BOTTOM_ROW = 14; // This array is used for mapping PACs -> row #, since ther
|
|||
|
||||
var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620, 0x1700, 0x1720, 0x1000, 0x1300, 0x1320, 0x1400, 0x1420]; // CEA-608 captions are rendered onto a 34x15 matrix of character
|
||||
// cells. The "bottom" row is the last element in the outer array.
|
||||
// We keep track of positioning information as we go by storing the
|
||||
// number of indentations and the tab offset in this buffer.
|
||||
|
||||
var createDisplayBuffer = function createDisplayBuffer() {
|
||||
var result = [],
|
||||
i = BOTTOM_ROW + 1;
|
||||
|
||||
while (i--) {
|
||||
result.push('');
|
||||
result.push({
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1439,9 +1461,9 @@ var Cea608Stream = function Cea608Stream(field, dataChannel) {
|
|||
this.startPts_ = packet.pts;
|
||||
} else if (data === this.BACKSPACE_) {
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
}
|
||||
} else if (data === this.ERASE_DISPLAYED_MEMORY_) {
|
||||
this.flushDisplayed(packet.pts);
|
||||
|
@ -1474,9 +1496,9 @@ var Cea608Stream = function Cea608Stream(field, dataChannel) {
|
|||
// backspace the "e" and insert "è".
|
||||
// Delete the previous character
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
} // Bitmask char0 so that we can apply character transformations
|
||||
// regardless of field and data channel.
|
||||
// Then byte-shift to the left and OR with char1 so we can pass the
|
||||
|
@ -1508,7 +1530,11 @@ var Cea608Stream = function Cea608Stream(field, dataChannel) {
|
|||
// increments, with an additional offset code of 1-3 to reach any
|
||||
// of the 32 columns specified by CEA-608. So all we need to do
|
||||
// here is increment the column cursor by the given offset.
|
||||
this.column_ += char1 & 0x03; // Detect PACs (Preamble Address Codes)
|
||||
var offset = char1 & 0x03; // For an offest value 1-3, set the offset for that caption
|
||||
// in the non-displayed array.
|
||||
|
||||
this.nonDisplayed_[this.row_].offset = offset;
|
||||
this.column_ += offset; // Detect PACs (Preamble Address Codes)
|
||||
} else if (this.isPAC(char0, char1)) {
|
||||
// There's no logic for PAC -> row mapping, so we have to just
|
||||
// find the row code in an array and use its index :(
|
||||
|
@ -1542,7 +1568,10 @@ var Cea608Stream = function Cea608Stream(field, dataChannel) {
|
|||
// increments the column cursor by 4, so we can get the desired
|
||||
// column position by bit-shifting to the right (to get n/2)
|
||||
// and multiplying by 4.
|
||||
this.column_ = ((data & 0xe) >> 1) * 4;
|
||||
var indentations = (data & 0xe) >> 1;
|
||||
this.column_ = indentations * 4; // add to the number of indentations for positioning
|
||||
|
||||
this.nonDisplayed_[this.row_].indent += indentations;
|
||||
}
|
||||
|
||||
if (this.isColorPAC(char1)) {
|
||||
|
@ -1573,29 +1602,52 @@ Cea608Stream.prototype = new Stream(); // Trigger a cue point that captures the
|
|||
// display buffer
|
||||
|
||||
Cea608Stream.prototype.flushDisplayed = function (pts) {
|
||||
var content = this.displayed_ // remove spaces from the start and end of the string
|
||||
.map(function (row, index) {
|
||||
try {
|
||||
return row.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
return '';
|
||||
var _this = this;
|
||||
|
||||
var logWarning = function logWarning(index) {
|
||||
_this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
};
|
||||
|
||||
var content = [];
|
||||
this.displayed_.forEach(function (row, i) {
|
||||
if (row && row.text && row.text.length) {
|
||||
try {
|
||||
// remove spaces from the start and end of the string
|
||||
row.text = row.text.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
logWarning(i);
|
||||
} // See the below link for more details on the following fields:
|
||||
// https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608
|
||||
|
||||
|
||||
if (row.text.length) {
|
||||
content.push({
|
||||
// The text to be displayed in the caption from this specific row, with whitespace removed.
|
||||
text: row.text,
|
||||
// Value between 1 and 15 representing the PAC row used to calculate line height.
|
||||
line: i + 1,
|
||||
// A number representing the indent position by percentage (CEA-608 PAC indent code).
|
||||
// The value will be a number between 10 and 80. Offset is used to add an aditional
|
||||
// value to the position if necessary.
|
||||
position: 10 + Math.min(70, row.indent * 10) + row.offset * 2.5
|
||||
});
|
||||
}
|
||||
} else if (row === undefined || row === null) {
|
||||
logWarning(i);
|
||||
}
|
||||
}, this) // combine all text rows to display in one cue
|
||||
.join('\n') // and remove blank rows from the start and end, but not the middle
|
||||
.replace(/^\n+|\n+$/g, '');
|
||||
});
|
||||
|
||||
if (content.length) {
|
||||
this.trigger('data', {
|
||||
startPts: this.startPts_,
|
||||
endPts: pts,
|
||||
text: content,
|
||||
content: content,
|
||||
stream: this.name_
|
||||
});
|
||||
}
|
||||
|
@ -1804,7 +1856,11 @@ Cea608Stream.prototype.setRollUp = function (pts, newBaseRow) {
|
|||
// move currently displayed captions (up or down) to the new base row
|
||||
for (var i = 0; i < this.rollUpRows_; i++) {
|
||||
this.displayed_[newBaseRow - i] = this.displayed_[this.row_ - i];
|
||||
this.displayed_[this.row_ - i] = '';
|
||||
this.displayed_[this.row_ - i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1841,27 +1897,35 @@ Cea608Stream.prototype.clearFormatting = function (pts) {
|
|||
|
||||
|
||||
Cea608Stream.prototype.popOn = function (pts, text) {
|
||||
var baseRow = this.nonDisplayed_[this.row_]; // buffer characters
|
||||
var baseRow = this.nonDisplayed_[this.row_].text; // buffer characters
|
||||
|
||||
baseRow += text;
|
||||
this.nonDisplayed_[this.row_] = baseRow;
|
||||
this.nonDisplayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.rollUp = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.shiftRowsUp_ = function () {
|
||||
var i; // clear out inactive rows
|
||||
|
||||
for (i = 0; i < this.topRow_; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
|
||||
for (i = this.row_ + 1; i < BOTTOM_ROW + 1; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
} // shift displayed rows up
|
||||
|
||||
|
||||
|
@ -1870,13 +1934,17 @@ Cea608Stream.prototype.shiftRowsUp_ = function () {
|
|||
} // clear out the bottom row
|
||||
|
||||
|
||||
this.displayed_[this.row_] = '';
|
||||
this.displayed_[this.row_] = {
|
||||
text: '',
|
||||
indent: 0,
|
||||
offset: 0
|
||||
};
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.paintOn = function (pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
}; // exports
|
||||
|
||||
|
||||
|
|
5
node_modules/mux.js/es/mp4/caption-parser.js
generated
vendored
5
node_modules/mux.js/es/mp4/caption-parser.js
generated
vendored
|
@ -248,7 +248,10 @@ var parseCaptionNals = function parseCaptionNals(segment, videoTrackId) {
|
|||
* @return {?Object[]} parsedCaptions - A list of captions or null if no video tracks
|
||||
* @return {Number} parsedCaptions[].startTime - The time to show the caption in seconds
|
||||
* @return {Number} parsedCaptions[].endTime - The time to stop showing the caption in seconds
|
||||
* @return {String} parsedCaptions[].text - The visible content of the caption
|
||||
* @return {Object[]} parsedCaptions[].content - A list of individual caption segments
|
||||
* @return {String} parsedCaptions[].content.text - The visible content of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.line - The line height from 1-15 for positioning of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.position - The column indent percentage for cue positioning from 10-80
|
||||
**/
|
||||
|
||||
|
||||
|
|
2
node_modules/mux.js/es/mp4/transmuxer.js
generated
vendored
2
node_modules/mux.js/es/mp4/transmuxer.js
generated
vendored
|
@ -654,7 +654,7 @@ _CoalesceStream = function CoalesceStream(options, metadataStream) {
|
|||
this.push = function (output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
} // buffer incoming id3 tags until the final flush
|
||||
|
||||
|
|
2
node_modules/mux.js/lib/flv/coalesce-stream.js
generated
vendored
2
node_modules/mux.js/lib/flv/coalesce-stream.js
generated
vendored
|
@ -35,7 +35,7 @@ var CoalesceStream = function(options) {
|
|||
this.push = function(output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
}
|
||||
// buffer incoming id3 tags until the final flush
|
||||
|
|
125
node_modules/mux.js/lib/m2ts/caption-stream.js
generated
vendored
125
node_modules/mux.js/lib/m2ts/caption-stream.js
generated
vendored
|
@ -688,18 +688,32 @@ Cea708Stream.prototype.handleText = function(i, service, options) {
|
|||
var char;
|
||||
var charCodeArray;
|
||||
|
||||
// Converts an array of bytes to a unicode hex string.
|
||||
function toHexString(byteArray) {
|
||||
return byteArray.map((byte) => {
|
||||
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join('');
|
||||
};
|
||||
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
}
|
||||
|
||||
// Use the TextDecoder if one was created for this service
|
||||
if (service.textDecoder_ && !isExtended) {
|
||||
if (isMultiByte) {
|
||||
charCodeArray = [currentByte, nextByte];
|
||||
i++;
|
||||
} else {
|
||||
charCodeArray = [currentByte];
|
||||
}
|
||||
|
||||
char = service.textDecoder_.decode(new Uint8Array(charCodeArray));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
// We assume any multi-byte char without a decoder is unicode.
|
||||
if (isMultiByte) {
|
||||
const unicode = toHexString(charCodeArray);
|
||||
// Takes a unicode hex string and creates a single character.
|
||||
char = String.fromCharCode(parseInt(unicode, 16));
|
||||
} else {
|
||||
char = get708CharFromCode(extended | currentByte);
|
||||
}
|
||||
}
|
||||
|
||||
if (win.pendingNewLine && !win.isEmpty()) {
|
||||
|
@ -1231,10 +1245,12 @@ var ROWS = [0x1100, 0x1120, 0x1200, 0x1220, 0x1500, 0x1520, 0x1600, 0x1620,
|
|||
|
||||
// CEA-608 captions are rendered onto a 34x15 matrix of character
|
||||
// cells. The "bottom" row is the last element in the outer array.
|
||||
// We keep track of positioning information as we go by storing the
|
||||
// number of indentations and the tab offset in this buffer.
|
||||
var createDisplayBuffer = function() {
|
||||
var result = [], i = BOTTOM_ROW + 1;
|
||||
while (i--) {
|
||||
result.push('');
|
||||
result.push({ text: '', indent: 0, offset: 0 });
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
@ -1312,9 +1328,9 @@ var Cea608Stream = function(field, dataChannel) {
|
|||
|
||||
} else if (data === this.BACKSPACE_) {
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
}
|
||||
} else if (data === this.ERASE_DISPLAYED_MEMORY_) {
|
||||
this.flushDisplayed(packet.pts);
|
||||
|
@ -1352,9 +1368,9 @@ var Cea608Stream = function(field, dataChannel) {
|
|||
|
||||
// Delete the previous character
|
||||
if (this.mode_ === 'popOn') {
|
||||
this.nonDisplayed_[this.row_] = this.nonDisplayed_[this.row_].slice(0, -1);
|
||||
this.nonDisplayed_[this.row_].text = this.nonDisplayed_[this.row_].text.slice(0, -1);
|
||||
} else {
|
||||
this.displayed_[this.row_] = this.displayed_[this.row_].slice(0, -1);
|
||||
this.displayed_[this.row_].text = this.displayed_[this.row_].text.slice(0, -1);
|
||||
}
|
||||
|
||||
// Bitmask char0 so that we can apply character transformations
|
||||
|
@ -1390,7 +1406,13 @@ var Cea608Stream = function(field, dataChannel) {
|
|||
// increments, with an additional offset code of 1-3 to reach any
|
||||
// of the 32 columns specified by CEA-608. So all we need to do
|
||||
// here is increment the column cursor by the given offset.
|
||||
this.column_ += (char1 & 0x03);
|
||||
const offset = (char1 & 0x03);
|
||||
|
||||
// For an offest value 1-3, set the offset for that caption
|
||||
// in the non-displayed array.
|
||||
this.nonDisplayed_[this.row_].offset = offset;
|
||||
|
||||
this.column_ += offset;
|
||||
|
||||
// Detect PACs (Preamble Address Codes)
|
||||
} else if (this.isPAC(char0, char1)) {
|
||||
|
@ -1427,7 +1449,11 @@ var Cea608Stream = function(field, dataChannel) {
|
|||
// increments the column cursor by 4, so we can get the desired
|
||||
// column position by bit-shifting to the right (to get n/2)
|
||||
// and multiplying by 4.
|
||||
this.column_ = ((data & 0xe) >> 1) * 4;
|
||||
const indentations = ((data & 0xe) >> 1);
|
||||
|
||||
this.column_ = indentations * 4;
|
||||
// add to the number of indentations for positioning
|
||||
this.nonDisplayed_[this.row_].indent += indentations;
|
||||
}
|
||||
|
||||
if (this.isColorPAC(char1)) {
|
||||
|
@ -1458,32 +1484,51 @@ Cea608Stream.prototype = new Stream();
|
|||
// Trigger a cue point that captures the current state of the
|
||||
// display buffer
|
||||
Cea608Stream.prototype.flushDisplayed = function(pts) {
|
||||
var content = this.displayed_
|
||||
// remove spaces from the start and end of the string
|
||||
.map(function(row, index) {
|
||||
const logWarning = (index) => {
|
||||
this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
};
|
||||
const content = [];
|
||||
|
||||
this.displayed_.forEach((row, i) => {
|
||||
if (row && row.text && row.text.length) {
|
||||
|
||||
try {
|
||||
return row.trim();
|
||||
// remove spaces from the start and end of the string
|
||||
row.text = row.text.trim();
|
||||
} catch (e) {
|
||||
// Ordinarily, this shouldn't happen. However, caption
|
||||
// parsing errors should not throw exceptions and
|
||||
// break playback.
|
||||
this.trigger('log', {
|
||||
level: 'warn',
|
||||
message: 'Skipping a malformed 608 caption at index ' + index + '.'
|
||||
});
|
||||
return '';
|
||||
logWarning(i);
|
||||
}
|
||||
}, this)
|
||||
// combine all text rows to display in one cue
|
||||
.join('\n')
|
||||
// and remove blank rows from the start and end, but not the middle
|
||||
.replace(/^\n+|\n+$/g, '');
|
||||
// See the below link for more details on the following fields:
|
||||
// https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608
|
||||
if (row.text.length) {
|
||||
content.push({
|
||||
// The text to be displayed in the caption from this specific row, with whitespace removed.
|
||||
text: row.text,
|
||||
// Value between 1 and 15 representing the PAC row used to calculate line height.
|
||||
line: i + 1,
|
||||
// A number representing the indent position by percentage (CEA-608 PAC indent code).
|
||||
// The value will be a number between 10 and 80. Offset is used to add an aditional
|
||||
// value to the position if necessary.
|
||||
position: 10 + Math.min(70, row.indent * 10) + (row.offset * 2.5),
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (row === undefined || row === null) {
|
||||
logWarning(i);
|
||||
}
|
||||
});
|
||||
|
||||
if (content.length) {
|
||||
this.trigger('data', {
|
||||
startPts: this.startPts_,
|
||||
endPts: pts,
|
||||
text: content,
|
||||
content,
|
||||
stream: this.name_
|
||||
});
|
||||
}
|
||||
|
@ -1686,7 +1731,7 @@ Cea608Stream.prototype.setRollUp = function(pts, newBaseRow) {
|
|||
// move currently displayed captions (up or down) to the new base row
|
||||
for (var i = 0; i < this.rollUpRows_; i++) {
|
||||
this.displayed_[newBaseRow - i] = this.displayed_[this.row_ - i];
|
||||
this.displayed_[this.row_ - i] = '';
|
||||
this.displayed_[this.row_ - i] = { text: '', indent: 0, offset: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1722,18 +1767,18 @@ Cea608Stream.prototype.clearFormatting = function(pts) {
|
|||
|
||||
// Mode Implementations
|
||||
Cea608Stream.prototype.popOn = function(pts, text) {
|
||||
var baseRow = this.nonDisplayed_[this.row_];
|
||||
var baseRow = this.nonDisplayed_[this.row_].text;
|
||||
|
||||
// buffer characters
|
||||
baseRow += text;
|
||||
this.nonDisplayed_[this.row_] = baseRow;
|
||||
this.nonDisplayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.rollUp = function(pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1741,24 +1786,24 @@ Cea608Stream.prototype.shiftRowsUp_ = function() {
|
|||
var i;
|
||||
// clear out inactive rows
|
||||
for (i = 0; i < this.topRow_; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = { text: '', indent: 0, offset: 0 };
|
||||
}
|
||||
for (i = this.row_ + 1; i < BOTTOM_ROW + 1; i++) {
|
||||
this.displayed_[i] = '';
|
||||
this.displayed_[i] = { text: '', indent: 0, offset: 0 };
|
||||
}
|
||||
// shift displayed rows up
|
||||
for (i = this.topRow_; i < this.row_; i++) {
|
||||
this.displayed_[i] = this.displayed_[i + 1];
|
||||
}
|
||||
// clear out the bottom row
|
||||
this.displayed_[this.row_] = '';
|
||||
this.displayed_[this.row_] = { text: '', indent: 0, offset: 0 };
|
||||
};
|
||||
|
||||
Cea608Stream.prototype.paintOn = function(pts, text) {
|
||||
var baseRow = this.displayed_[this.row_];
|
||||
var baseRow = this.displayed_[this.row_].text;
|
||||
|
||||
baseRow += text;
|
||||
this.displayed_[this.row_] = baseRow;
|
||||
this.displayed_[this.row_].text = baseRow;
|
||||
};
|
||||
|
||||
// exports
|
||||
|
|
5
node_modules/mux.js/lib/mp4/caption-parser.js
generated
vendored
5
node_modules/mux.js/lib/mp4/caption-parser.js
generated
vendored
|
@ -245,7 +245,10 @@ var parseCaptionNals = function(segment, videoTrackId) {
|
|||
* @return {?Object[]} parsedCaptions - A list of captions or null if no video tracks
|
||||
* @return {Number} parsedCaptions[].startTime - The time to show the caption in seconds
|
||||
* @return {Number} parsedCaptions[].endTime - The time to stop showing the caption in seconds
|
||||
* @return {String} parsedCaptions[].text - The visible content of the caption
|
||||
* @return {Object[]} parsedCaptions[].content - A list of individual caption segments
|
||||
* @return {String} parsedCaptions[].content.text - The visible content of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.line - The line height from 1-15 for positioning of the caption segment
|
||||
* @return {Number} parsedCaptions[].content.position - The column indent percentage for cue positioning from 10-80
|
||||
**/
|
||||
var parseEmbeddedCaptions = function(segment, trackId, timescale) {
|
||||
var captionNals;
|
||||
|
|
2
node_modules/mux.js/lib/mp4/transmuxer.js
generated
vendored
2
node_modules/mux.js/lib/mp4/transmuxer.js
generated
vendored
|
@ -727,7 +727,7 @@ CoalesceStream = function(options, metadataStream) {
|
|||
this.push = function(output) {
|
||||
// buffer incoming captions until the associated video segment
|
||||
// finishes
|
||||
if (output.text) {
|
||||
if (output.content || output.text) {
|
||||
return this.pendingCaptions.push(output);
|
||||
}
|
||||
// buffer incoming id3 tags until the final flush
|
||||
|
|
2
node_modules/mux.js/package.json
generated
vendored
2
node_modules/mux.js/package.json
generated
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mux.js",
|
||||
"version": "6.3.0",
|
||||
"version": "7.0.1",
|
||||
"description": "A collection of lightweight utilities for inspecting and manipulating video container formats.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
6
node_modules/mux.js/test/caption-parser.test.js
generated
vendored
6
node_modules/mux.js/test/caption-parser.test.js
generated
vendored
|
@ -49,7 +49,7 @@ QUnit.test('parse captions from real segment', function(assert) {
|
|||
cc = captionParser.parse(dashSegment, trackIds, timescales);
|
||||
|
||||
assert.equal(cc.captions.length, 1);
|
||||
assert.equal(cc.captions[0].text, '00:00:00',
|
||||
assert.equal(cc.captions[0].content[0].text, '00:00:00',
|
||||
'real segment caption has correct text');
|
||||
assert.equal(cc.captions[0].stream, 'CC1',
|
||||
'real segment caption has correct stream');
|
||||
|
@ -86,7 +86,7 @@ QUnit.test('parseTrackId for version 0 and version 1 boxes', function(assert) {
|
|||
{ 1: 90000 }); // timescales);
|
||||
|
||||
assert.equal(v0Captions.captions.length, 1, 'got 1 version0 caption');
|
||||
assert.equal(v0Captions.captions[0].text, 'test string #1',
|
||||
assert.equal(v0Captions.captions[0].content[0].text, 'test string #1',
|
||||
'got the expected version0 caption text');
|
||||
assert.equal(v0Captions.captions[0].stream, 'CC1',
|
||||
'returned the correct caption stream CC1');
|
||||
|
@ -108,7 +108,7 @@ QUnit.test('parseTrackId for version 0 and version 1 boxes', function(assert) {
|
|||
{ 2: 90000 }); // timescales
|
||||
|
||||
assert.equal(v1Captions.captions.length, 1, 'got version1 caption');
|
||||
assert.equal(v1Captions.captions[0].text, 'test string #2',
|
||||
assert.equal(v1Captions.captions[0].content[0].text, 'test string #2',
|
||||
'got the expected version1 caption text');
|
||||
assert.equal(v1Captions.captions[0].stream, 'CC4',
|
||||
'returned the correct caption stream CC4');
|
||||
|
|
490
node_modules/mux.js/test/caption-stream.test.js
generated
vendored
490
node_modules/mux.js/test/caption-stream.test.js
generated
vendored
|
@ -261,8 +261,8 @@ QUnit.test('can be parsed from a segment', function(assert) {
|
|||
transmuxer.flush();
|
||||
|
||||
assert.equal(captions.length, 2, 'parsed two captions');
|
||||
assert.equal(captions[0].text.indexOf('ASUKA'), 0, 'parsed the start of the first caption');
|
||||
assert.ok(captions[0].text.indexOf('Japanese') > 0, 'parsed the end of the first caption');
|
||||
assert.equal(captions[0].content[0].text.indexOf('ASUKA'), 0, 'parsed the start of the first caption');
|
||||
assert.ok(captions[0].content[0].text.indexOf('Japanese') > 0, 'parsed the end of the first caption');
|
||||
assert.equal(captions[0].startTime, 1, 'parsed the start time');
|
||||
assert.equal(captions[0].endTime, 4, 'parsed the end time');
|
||||
});
|
||||
|
@ -291,8 +291,8 @@ QUnit.test('dispatches caption track information', function(assert) {
|
|||
|
||||
assert.deepEqual(captionStreams, {CC1: true, CC3: true}, 'found captions in CC1 and CC3');
|
||||
assert.equal(captions.length, 4, 'parsed eight captions');
|
||||
assert.equal(captions[0].text, 'être une période de questions', 'parsed the text of the first caption in CC3');
|
||||
assert.equal(captions[1].text, 'PERIOD, FOLKS.', 'parsed the text of the first caption in CC1');
|
||||
assert.equal(captions[0].content[0].text, 'être une période de questions', 'parsed the text of the first caption in CC3');
|
||||
assert.equal(captions[1].content[0].text, 'PERIOD, FOLKS.', 'parsed the text of the first caption in CC1');
|
||||
});
|
||||
|
||||
QUnit.test('sorting is fun', function(assert) {
|
||||
|
@ -341,8 +341,8 @@ QUnit.test('sorting is fun', function(assert) {
|
|||
captionStream.flush();
|
||||
|
||||
assert.equal(captions.length, 2, 'detected two captions');
|
||||
assert.equal(captions[0].text, 'test string #1', 'parsed caption 1');
|
||||
assert.equal(captions[1].text, 'test string #2', 'parsed caption 2');
|
||||
assert.equal(captions[0].content[0].text, 'test string #1', 'parsed caption 1');
|
||||
assert.equal(captions[1].content[0].text, 'test string #2', 'parsed caption 2');
|
||||
});
|
||||
|
||||
QUnit.test('drops duplicate segments', function(assert) {
|
||||
|
@ -405,7 +405,7 @@ QUnit.test('drops duplicate segments', function(assert) {
|
|||
captionStream.flush();
|
||||
|
||||
assert.equal(captions.length, 1, 'detected one caption');
|
||||
assert.equal(captions[0].text, 'test string data', 'parsed caption properly');
|
||||
assert.equal(captions[0].content[0].text, 'test string data', 'parsed caption properly');
|
||||
});
|
||||
|
||||
QUnit.test('drops duplicate segments with multi-segment DTS values', function(assert) {
|
||||
|
@ -555,8 +555,8 @@ QUnit.test('drops duplicate segments with multi-segment DTS values', function(as
|
|||
captionStream.flush();
|
||||
|
||||
assert.equal(captions.length, 2, 'detected two captions');
|
||||
assert.equal(captions[0].text, 'test string data stuff', 'parsed caption properly');
|
||||
assert.equal(captions[1].text, 'and even more text data here!', 'parsed caption properly');
|
||||
assert.equal(captions[0].content[0].text, 'test string data stuff', 'parsed caption properly');
|
||||
assert.equal(captions[1].content[0].text, 'and even more text data here!', 'parsed caption properly');
|
||||
});
|
||||
|
||||
QUnit.test('doesn\'t ignore older segments if reset', function(assert) {
|
||||
|
@ -647,7 +647,7 @@ QUnit.test('doesn\'t ignore older segments if reset', function(assert) {
|
|||
assert.equal(captionStream.latestDts_, 4000, 'DTS is tracked correctly');
|
||||
|
||||
assert.equal(captions.length, 1, 'detected one caption');
|
||||
assert.equal(captions[0].text, 'after reset data!!', 'parsed caption properly');
|
||||
assert.equal(captions[0].content[0].text, 'after reset data!!', 'parsed caption properly');
|
||||
});
|
||||
|
||||
QUnit.test('extracts all theoretical caption channels', function(assert) {
|
||||
|
@ -690,13 +690,14 @@ QUnit.test('extracts all theoretical caption channels', function(assert) {
|
|||
captionStream.flush();
|
||||
|
||||
assert.equal(captions.length, 6, 'got all captions');
|
||||
assert.equal(captions[0].text, '1a', 'cc1 first row');
|
||||
assert.equal(captions[1].text, '2a', 'cc2 first row');
|
||||
assert.equal(captions[2].text, '1a\n1b1c', 'cc1 first and second row');
|
||||
assert.equal(captions[3].text, '3a', 'cc3 first row');
|
||||
assert.equal(captions[4].text, '4a4b', 'cc4 first row');
|
||||
assert.equal(captions[5].text, '2a\n2b', 'cc2 first and second row');
|
||||
|
||||
assert.equal(captions[0].content[0].text, '1a', 'cc1 first row');
|
||||
assert.equal(captions[1].content[0].text, '2a', 'cc2 first row');
|
||||
assert.equal(captions[2].content[0].text, '1a', 'cc1 first row');
|
||||
assert.equal(captions[2].content[1].text, '1b1c', 'cc1 second row');
|
||||
assert.equal(captions[3].content[0].text, '3a', 'cc3 first row');
|
||||
assert.equal(captions[4].content[0].text, '4a4b', 'cc4 first row');
|
||||
assert.equal(captions[5].content[0].text, '2a', 'cc2 first row');
|
||||
assert.equal(captions[5].content[1].text, '2b', 'cc2 second row');
|
||||
});
|
||||
|
||||
QUnit.test('drops data until first command that sets activeChannel for a field', function(assert) {
|
||||
|
@ -763,9 +764,9 @@ QUnit.test('drops data until first command that sets activeChannel for a field',
|
|||
captionStream.flush();
|
||||
|
||||
assert.equal(captions.length, 2, 'received 2 captions');
|
||||
assert.equal(captions[0].text, 'field0', 'received only confirmed field0 data');
|
||||
assert.equal(captions[0].content[0].text, 'field0', 'received only confirmed field0 data');
|
||||
assert.equal(captions[0].stream, 'CC1', 'caption went to right channel');
|
||||
assert.equal(captions[1].text, 'field1', 'received only confirmed field1 data');
|
||||
assert.equal(captions[1].content[0].text, 'field1', 'received only confirmed field1 data');
|
||||
assert.equal(captions[1].stream, 'CC4', 'caption went to right channel');
|
||||
});
|
||||
|
||||
|
@ -855,33 +856,33 @@ QUnit.test('clears buffer and drops data until first command that sets activeCha
|
|||
seiNals1.forEach(captionStream.push, captionStream);
|
||||
captionStream.flush();
|
||||
|
||||
assert.equal(captionStream.ccStreams_[0].nonDisplayed_[14], 'field0',
|
||||
assert.equal(captionStream.ccStreams_[0].nonDisplayed_[14].text, 'field0',
|
||||
'there is data in non-displayed memory for field 0 before reset');
|
||||
assert.equal(captionStream.ccStreams_[3].nonDisplayed_[14], 'field1',
|
||||
assert.equal(captionStream.ccStreams_[3].nonDisplayed_[14].text, 'field1',
|
||||
'there is data in non-displayed memory for field 1 before reset');
|
||||
assert.equal(captionStream.ccStreams_[0].displayed_[14], 'field0',
|
||||
assert.equal(captionStream.ccStreams_[0].displayed_[14].text, 'field0',
|
||||
'there is data in displayed memory for field 0 before reset');
|
||||
assert.equal(captionStream.ccStreams_[3].displayed_[14], 'field1',
|
||||
assert.equal(captionStream.ccStreams_[3].displayed_[14].text, 'field1',
|
||||
'there is data in displayed memory for field 1 before reset');
|
||||
|
||||
captionStream.reset();
|
||||
|
||||
assert.equal(captionStream.ccStreams_[0].nonDisplayed_[14], '',
|
||||
assert.equal(captionStream.ccStreams_[0].nonDisplayed_[14].text, '',
|
||||
'there is no data in non-displayed memory for field 0 after reset');
|
||||
assert.equal(captionStream.ccStreams_[3].nonDisplayed_[14], '',
|
||||
assert.equal(captionStream.ccStreams_[3].nonDisplayed_[14].text, '',
|
||||
'there is no data in non-displayed memory for field 1 after reset');
|
||||
assert.equal(captionStream.ccStreams_[0].displayed_[14], '',
|
||||
assert.equal(captionStream.ccStreams_[0].displayed_[14].text, '',
|
||||
'there is no data in displayed memory for field 0 after reset');
|
||||
assert.equal(captionStream.ccStreams_[3].displayed_[14], '',
|
||||
assert.equal(captionStream.ccStreams_[3].displayed_[14].text, '',
|
||||
'there is no data in displayed memory for field 1 after reset');
|
||||
|
||||
seiNals2.forEach(captionStream.push, captionStream);
|
||||
captionStream.flush();
|
||||
|
||||
assert.equal(captions.length, 2, 'detected two captions');
|
||||
assert.equal(captions[0].text, 'but this', 'parsed caption properly');
|
||||
assert.equal(captions[0].content[0].text, 'but this', 'parsed caption properly');
|
||||
assert.equal(captions[0].stream, 'CC1', 'caption went to right channel');
|
||||
assert.equal(captions[1].text, 'and this', 'parsed caption properly');
|
||||
assert.equal(captions[1].content[0].text, 'and this', 'parsed caption properly');
|
||||
assert.equal(captions[1].stream, 'CC4', 'caption went to right channel');
|
||||
});
|
||||
|
||||
|
@ -898,10 +899,15 @@ QUnit.test("don't mess up 608 captions when 708 are present", function(assert) {
|
|||
captionStream.flush();
|
||||
|
||||
assert.equal(captions.length, 3, 'parsed three captions');
|
||||
assert.equal(captions[0].text, 'BUT IT\'S NOT SUFFERING\nRIGHW.', 'parsed first caption correctly');
|
||||
// first caption stream
|
||||
assert.equal(captions[0].content[0].text, 'BUT IT\'S NOT SUFFERING', 'first stream: parsed first content text correctly');
|
||||
assert.equal(captions[0].content[1].text, 'RIGHW.', 'first stream: parsed second content text correctly');
|
||||
// there is also bad data in the captions, but the null ascii character is removed
|
||||
assert.equal(captions[1].text, 'IT\'S NOT A THREAT TO ANYBODY.', 'parsed second caption correctly');
|
||||
assert.equal(captions[2].text, 'WE TRY NOT TO PUT AN ANIMAL DOWN\nIF WE DON\'T HAVE TO.', 'parsed third caption correctly');
|
||||
// second caption stream
|
||||
assert.equal(captions[1].content[0].text, 'IT\'S NOT A THREAT TO ANYBODY.', 'second stream: parsed content text correctly');
|
||||
// third stream
|
||||
assert.equal(captions[2].content[0].text, 'WE TRY NOT TO PUT AN ANIMAL DOWN', 'third stream: parsed first content text correctly');
|
||||
assert.equal(captions[2].content[1].text, 'IF WE DON\'T HAVE TO.', 'third stream: parsed second content text correctly');
|
||||
});
|
||||
|
||||
QUnit.test("both 608 and 708 captions are available by default", function(assert) {
|
||||
|
@ -1009,7 +1015,7 @@ QUnit.test('ignores XDS and Text packets', function(assert) {
|
|||
captionStream.flush();
|
||||
|
||||
assert.equal(captions.length, 1, 'only parsed real caption');
|
||||
assert.equal(captions[0].text, 'hi', 'caption is correct');
|
||||
assert.equal(captions[0].content[0].text, 'hi', 'caption is correct');
|
||||
|
||||
});
|
||||
|
||||
|
@ -1051,9 +1057,9 @@ QUnit.test('special and extended character codes work regardless of field and da
|
|||
seiNals.forEach(captionStream.push, captionStream);
|
||||
captionStream.flush();
|
||||
|
||||
assert.deepEqual(captions[0].text, String.fromCharCode(0xae), 'CC2 special character correct');
|
||||
assert.deepEqual(captions[1].text, String.fromCharCode(0xab), 'CC3 extended character correct');
|
||||
assert.deepEqual(captions[2].text, String.fromCharCode(0xbb), 'CC4 extended character correct');
|
||||
assert.deepEqual(captions[0].content[0].text, String.fromCharCode(0xae), 'CC2 special character correct');
|
||||
assert.deepEqual(captions[1].content[0].text, String.fromCharCode(0xab), 'CC3 extended character correct');
|
||||
assert.deepEqual(captions[2].content[0].text, String.fromCharCode(0xbb), 'CC4 extended character correct');
|
||||
});
|
||||
|
||||
QUnit.test('number of roll up rows takes precedence over base row command', function(assert) {
|
||||
|
@ -1100,8 +1106,9 @@ QUnit.test('number of roll up rows takes precedence over base row command', func
|
|||
seis.forEach(captionStream.push, captionStream);
|
||||
captionStream.flush();
|
||||
|
||||
assert.deepEqual(captions[0].text, '-', 'RU2 caption is correct');
|
||||
assert.deepEqual(captions[1].text, '-\nso', 'RU3 caption is correct');
|
||||
assert.deepEqual(captions[0].content[0].text, '-', 'RU2 caption is correct');
|
||||
assert.deepEqual(captions[1].content[0].text, '-', 'first RU3 caption is correct');
|
||||
assert.deepEqual(captions[1].content[1].text, 'so', 'second RU3 caption is correct');
|
||||
|
||||
packets = [
|
||||
// switching from row 11 to 0
|
||||
|
@ -1119,7 +1126,8 @@ QUnit.test('number of roll up rows takes precedence over base row command', func
|
|||
seis.forEach(captionStream.push, captionStream);
|
||||
captionStream.flush();
|
||||
|
||||
assert.deepEqual(captions[2].text, '-\nso', 'RU3 caption is correct');
|
||||
assert.deepEqual(captions[2].content[0].text, '-', 'first RU3 caption is correct');
|
||||
assert.deepEqual(captions[2].content[1].text, 'so', 'second RU3 caption is correct');
|
||||
});
|
||||
|
||||
var cea608Stream;
|
||||
|
@ -1162,7 +1170,7 @@ QUnit.test('converts non-ASCII character codes to ASCII', function(assert) {
|
|||
});
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text,
|
||||
assert.equal(captions[0].content[0].text,
|
||||
String.fromCharCode(0xe1, 0xe9, 0xed, 0xf3, 0xfa, 0xe7, 0xf7, 0xd1, 0xf1, 0x2588),
|
||||
'translated non-standard characters');
|
||||
});
|
||||
|
@ -1205,7 +1213,7 @@ QUnit.test('properly handles special character codes', function(assert) {
|
|||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions[0].text,
|
||||
assert.equal(captions[0].content[0].text,
|
||||
String.fromCharCode(0xae, 0xb0, 0xbd, 0xbf, 0x2122, 0xa2, 0xa3, 0x266a,
|
||||
0xe0, 0xa0, 0xe8, 0xe2, 0xea, 0xee, 0xf4, 0xfb),
|
||||
'translated special characters');
|
||||
|
@ -1248,7 +1256,7 @@ QUnit.test('properly handles extended character codes', function(assert) {
|
|||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions[0].text, '«LÀ-LÅ LAÑD♪»',
|
||||
assert.equal(captions[0].content[0].text, '«LÀ-LÅ LAÑD♪»',
|
||||
'translated special characters');
|
||||
});
|
||||
|
||||
|
@ -1278,7 +1286,11 @@ QUnit.test('pop-on mode', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 1000,
|
||||
endPts: 10 * 1000,
|
||||
text: 'hi',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: 'hi'
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'parsed the caption');
|
||||
});
|
||||
|
@ -1313,7 +1325,11 @@ QUnit.test('ignores null characters', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 1000,
|
||||
endPts: 10 * 1000,
|
||||
text: 'mu x',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: 'mu x'
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'ignored null characters');
|
||||
});
|
||||
|
@ -1354,24 +1370,36 @@ QUnit.test('recognizes the Erase Displayed Memory command', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 1 * 1000,
|
||||
endPts: 1.5 * 1000,
|
||||
text: '01',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '01'
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'parsed the first caption');
|
||||
assert.deepEqual(captions[1], {
|
||||
startPts: 2 * 1000,
|
||||
endPts: 3 * 1000,
|
||||
text: '23',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '23'
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'parsed the second caption');
|
||||
assert.deepEqual(captions[2], {
|
||||
startPts: 3 * 1000,
|
||||
endPts: 4 * 1000,
|
||||
text: '34',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '34'
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'parsed the third caption');
|
||||
});
|
||||
|
||||
QUnit.test('backspaces are applied to non-displayed memory for pop-on mode', function(assert) {
|
||||
QUnit.test('correct content text is added to non-displayed memory for pop-on mode', function(assert) {
|
||||
var captions = [], packets;
|
||||
cea608Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
|
@ -1402,7 +1430,8 @@ QUnit.test('backspaces are applied to non-displayed memory for pop-on mode', fun
|
|||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 1, 'detected a caption');
|
||||
assert.equal(captions[0].text, '310\n\n023', 'applied the backspaces');
|
||||
assert.equal(captions[0].content[0].text, '310', 'first content text');
|
||||
assert.equal(captions[0].content[1].text, '023', 'second content text');
|
||||
});
|
||||
|
||||
QUnit.test('backspaces on cleared memory are no-ops', function(assert) {
|
||||
|
@ -1455,7 +1484,11 @@ QUnit.test('recognizes the Erase Non-Displayed Memory command', function(assert)
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 1 * 1000,
|
||||
endPts: 2 * 1000,
|
||||
text: '23',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '23'
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'cleared the non-displayed memory');
|
||||
});
|
||||
|
@ -1483,7 +1516,7 @@ QUnit.test('ignores unrecognized commands', function(assert) {
|
|||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions[0].text, '01', 'skipped the unrecognized commands');
|
||||
assert.equal(captions[0].content[0].text, '01', 'skipped the unrecognized commands');
|
||||
});
|
||||
|
||||
QUnit.skip('applies preamble address codes', function(assert) {
|
||||
|
@ -1513,7 +1546,7 @@ QUnit.test('applies mid-row underline', function(assert) {
|
|||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text, 'no <u>yes.</u>', 'properly closed by CR');
|
||||
assert.equal(captions[0].content[0].text, 'no <u>yes.</u>', 'properly closed by CR');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
|
@ -1536,7 +1569,7 @@ QUnit.test('applies mid-row italics', function(assert) {
|
|||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text, 'no <i>yes.</i>', 'properly closed by CR');
|
||||
assert.equal(captions[0].content[0].text, 'no <i>yes.</i>', 'properly closed by CR');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
|
@ -1559,7 +1592,7 @@ QUnit.test('applies mid-row italics underline', function(assert) {
|
|||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text, 'no <i><u>yes.</u></i>', 'properly closed by CR');
|
||||
assert.equal(captions[0].content[0].text, 'no <i><u>yes.</u></i>', 'properly closed by CR');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
|
@ -1583,7 +1616,7 @@ QUnit.test('applies PAC underline', function(assert) {
|
|||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text, '<u>yes.</u>', 'properly closed by CR');
|
||||
assert.equal(captions[0].content[0].text, '<u>yes.</u>', 'properly closed by CR');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
|
@ -1605,7 +1638,7 @@ QUnit.test('applies PAC white italics', function(assert) {
|
|||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text, '<i>yes.</i>', 'properly closed by CR');
|
||||
assert.equal(captions[0].content[0].text, '<i>yes.</i>', 'properly closed by CR');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
|
@ -1627,11 +1660,11 @@ QUnit.test('applies PAC white italics underline', function(assert) {
|
|||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text, '<u><i>yes.</i></u>', 'properly closed by CR');
|
||||
assert.equal(captions[0].content[0].text, '<u><i>yes.</i></u>', 'properly closed by CR');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
QUnit.test('closes formatting at PAC row change', function(assert) {
|
||||
QUnit.test('includes all caption text at PAC row change', function(assert) {
|
||||
var captions = [];
|
||||
cea608Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
|
@ -1656,7 +1689,8 @@ QUnit.test('closes formatting at PAC row change', function(assert) {
|
|||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text, '<u><i>yes.</i></u>\nno', 'properly closed by PAC row change');
|
||||
assert.equal(captions[0].content[0].text, '<u><i>yes.</i></u>', 'first content text');
|
||||
assert.equal(captions[0].content[1].text, 'no', 'second content text');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
|
@ -1682,7 +1716,7 @@ QUnit.test('closes formatting at EOC', function(assert) {
|
|||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].text, '<u><i>yes.</i></u>', 'properly closed by EOC');
|
||||
assert.equal(captions[0].content[0].text, '<u><i>yes.</i></u>', 'properly closed by EOC');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
|
@ -1707,7 +1741,7 @@ QUnit.test('closes formatting at negating mid-row code', function(assert) {
|
|||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
cea608Stream.flushDisplayed();
|
||||
assert.equal(captions[0].text, 'no <i><u>yes.</u></i> no', 'properly closed by negating mid-row code');
|
||||
assert.equal(captions[0].content[0].text, 'no <i><u>yes.</u></i> no', 'properly closed by negating mid-row code');
|
||||
assert.deepEqual(cea608Stream.formatting_, [], 'formatting is empty');
|
||||
});
|
||||
|
||||
|
@ -1733,7 +1767,11 @@ QUnit.test('roll-up display mode', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 0 * 1000,
|
||||
endPts: 3 * 1000,
|
||||
text: '01',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '01'
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'parsed the caption');
|
||||
captions = [];
|
||||
|
@ -1755,7 +1793,18 @@ QUnit.test('roll-up display mode', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 3 * 1000,
|
||||
endPts: 5 * 1000,
|
||||
text: '01\n23',
|
||||
content: [
|
||||
{
|
||||
line: 14,
|
||||
position: 10,
|
||||
text: '01'
|
||||
},
|
||||
{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '23'
|
||||
}
|
||||
],
|
||||
stream: 'CC1'
|
||||
}, 'parsed the new caption and kept the caption up after the new caption');
|
||||
});
|
||||
|
@ -1783,7 +1832,11 @@ QUnit.test('roll-up displays multiple rows simultaneously', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 0 * 1000,
|
||||
endPts: 1 * 1000,
|
||||
text: '01',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '01'
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'created a caption for the first period');
|
||||
captions = [];
|
||||
|
@ -1803,7 +1856,18 @@ QUnit.test('roll-up displays multiple rows simultaneously', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 1 * 1000,
|
||||
endPts: 3 * 1000,
|
||||
text: '01\n23',
|
||||
content: [
|
||||
{
|
||||
line: 14,
|
||||
position: 10,
|
||||
text: '01'
|
||||
},
|
||||
{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '23'
|
||||
}
|
||||
],
|
||||
stream: 'CC1'
|
||||
}, 'created the top and bottom rows after the shift up');
|
||||
captions = [];
|
||||
|
@ -1823,7 +1887,18 @@ QUnit.test('roll-up displays multiple rows simultaneously', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 3 * 1000,
|
||||
endPts: 5 * 1000,
|
||||
text: '23\n45',
|
||||
"content": [
|
||||
{
|
||||
line: 14,
|
||||
position: 10,
|
||||
text: '23'
|
||||
},
|
||||
{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: '45'
|
||||
}
|
||||
],
|
||||
stream: 'CC1'
|
||||
}, 'created the top and bottom rows after the shift up');
|
||||
});
|
||||
|
@ -1894,13 +1969,13 @@ QUnit.test('switching to roll-up from pop-on wipes memories and flushes captions
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
var displayed = cea608Stream.displayed_.reduce(function(acc, val) {
|
||||
acc += val;
|
||||
acc += val.text;
|
||||
return acc;
|
||||
});
|
||||
}, '');
|
||||
var nonDisplayed = cea608Stream.nonDisplayed_.reduce(function(acc, val) {
|
||||
acc += val;
|
||||
acc += val.text;
|
||||
return acc;
|
||||
});
|
||||
}, '');
|
||||
|
||||
assert.equal(captions.length, 2, 'both captions flushed');
|
||||
assert.equal(displayed, '', 'displayed memory is wiped');
|
||||
|
@ -1908,13 +1983,21 @@ QUnit.test('switching to roll-up from pop-on wipes memories and flushes captions
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 1000,
|
||||
endPts: 2000,
|
||||
text: 'hi',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: 'hi',
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'first caption correct');
|
||||
assert.deepEqual(captions[1], {
|
||||
startPts: 2000,
|
||||
endPts: 3000,
|
||||
text: 'oh',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: 'oh',
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'second caption correct');
|
||||
});
|
||||
|
@ -1934,13 +2017,13 @@ QUnit.test('switching to roll-up from paint-on wipes memories and flushes captio
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
var displayed = cea608Stream.displayed_.reduce(function(acc, val) {
|
||||
acc += val;
|
||||
acc += val.text;
|
||||
return acc;
|
||||
});
|
||||
}, '');
|
||||
var nonDisplayed = cea608Stream.nonDisplayed_.reduce(function(acc, val) {
|
||||
acc += val;
|
||||
acc += val.text;
|
||||
return acc;
|
||||
});
|
||||
}, '');
|
||||
|
||||
assert.equal(captions.length, 1, 'flushed caption');
|
||||
assert.equal(displayed, '', 'displayed memory is wiped');
|
||||
|
@ -1948,7 +2031,11 @@ QUnit.test('switching to roll-up from paint-on wipes memories and flushes captio
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 0,
|
||||
endPts: 1000,
|
||||
text: 'hi',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: 'hi',
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'caption correct');
|
||||
});
|
||||
|
@ -1983,10 +2070,10 @@ QUnit.test('switching to paint-on from pop-on flushes display', function(assert)
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 2, 'detected 2 captions');
|
||||
assert.equal(captions[0].text, 'hi', 'pop-on caption received');
|
||||
assert.equal(captions[0].content[0].text, 'hi', 'pop-on caption received');
|
||||
assert.equal(captions[0].startPts, 1000, 'proper start pts');
|
||||
assert.equal(captions[0].endPts, 2000, 'proper end pts');
|
||||
assert.equal(captions[1].text, 'io', 'paint-on caption received');
|
||||
assert.equal(captions[1].content[0].text, 'io', 'paint-on caption received');
|
||||
assert.equal(captions[1].startPts, 2000, 'proper start pts');
|
||||
assert.equal(captions[1].endPts, 4000, 'proper end pts');
|
||||
});
|
||||
|
@ -2017,7 +2104,7 @@ QUnit.test('backspaces are reflected in the generated captions', function(assert
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 1, 'detected a caption');
|
||||
assert.equal(captions[0].text, '023', 'applied the backspace');
|
||||
assert.equal(captions[0].content[0].text, '023', 'applied the backspace');
|
||||
});
|
||||
|
||||
QUnit.test('backspaces can remove a caption entirely', function(assert) {
|
||||
|
@ -2079,7 +2166,7 @@ QUnit.test('a second identical control code immediately following the first is i
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 1, 'caption emitted');
|
||||
assert.equal(captions[0].text, '01', 'only two backspaces processed');
|
||||
assert.equal(captions[0].content[0].text, '01', 'only two backspaces processed');
|
||||
});
|
||||
|
||||
QUnit.test('a second identical control code separated by only padding from the first is ignored', function(assert) {
|
||||
|
@ -2115,7 +2202,7 @@ QUnit.test('a second identical control code separated by only padding from the f
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 1, 'caption emitted');
|
||||
assert.equal(captions[0].text, '010', 'only one backspace processed');
|
||||
assert.equal(captions[0].content[0].text, '010', 'only one backspace processed');
|
||||
});
|
||||
|
||||
QUnit.test('preamble address codes on same row are NOT converted into spaces', function(assert) {
|
||||
|
@ -2145,10 +2232,10 @@ QUnit.test('preamble address codes on same row are NOT converted into spaces', f
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 1, 'caption emitted');
|
||||
assert.equal(captions[0].text, '0102', 'PACs were NOT converted to space');
|
||||
assert.equal(captions[0].content[0].text, '0102', 'PACs were NOT converted to space');
|
||||
});
|
||||
|
||||
QUnit.test('preserves newlines from PACs in pop-on mode', function(assert) {
|
||||
QUnit.test('generates correct content with PACs in pop-on mode', function(assert) {
|
||||
var captions = [];
|
||||
cea608Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
|
@ -2184,7 +2271,9 @@ QUnit.test('preserves newlines from PACs in pop-on mode', function(assert) {
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 1, 'caption emitted');
|
||||
assert.equal(captions[0].text, 'TEST\n\nSTRING\nDATA', 'Position PACs were converted to newlines');
|
||||
assert.equal(captions[0].content[0].text, 'TEST', 'first content text');
|
||||
assert.equal(captions[0].content[1].text, 'STRING', 'second content text');
|
||||
assert.equal(captions[0].content[2].text, 'DATA', 'third content text');
|
||||
});
|
||||
|
||||
QUnit.test('extracts real-world cc1 and cc3 channels', function(assert) {
|
||||
|
@ -2252,14 +2341,14 @@ QUnit.test('extracts real-world cc1 and cc3 channels', function(assert) {
|
|||
cea608Stream3.push(packet);
|
||||
});
|
||||
|
||||
var cc1 = {stream: 'CC1', text: 'PERIOD, FOLKS.'};
|
||||
var cc3 = {stream: 'CC3', text: 'être une période de questions'};
|
||||
var cc1 = {stream: 'CC1', content: [{ text: 'PERIOD, FOLKS.'}] };
|
||||
var cc3 = {stream: 'CC3', content: [{ text: 'être une période de questions' }] };
|
||||
|
||||
assert.equal(captions.length, 2, 'caption emitted');
|
||||
assert.equal(captions[0].stream, cc1.stream, 'cc1 stream detected');
|
||||
assert.equal(captions[0].text, cc1.text, 'cc1 stream extracted successfully');
|
||||
assert.equal(captions[0].content[0].text, cc1.content[0].text, 'cc1 stream extracted successfully');
|
||||
assert.equal(captions[1].stream, cc3.stream, 'cc3 stream detected');
|
||||
assert.equal(captions[1].text, cc3.text, 'cc3 stream extracted successfully');
|
||||
assert.equal(captions[1].content[0].text, cc3.content[0].text, 'cc3 stream extracted successfully');
|
||||
});
|
||||
|
||||
QUnit.test('backspaces stop at the beginning of the line', function(assert) {
|
||||
|
@ -2307,7 +2396,7 @@ QUnit.test('reset works', function(assert) {
|
|||
{ pts: 0, ccData: characters('01'), type: 0 }
|
||||
].forEach(cea608Stream.push, cea608Stream);
|
||||
var buffer = cea608Stream.displayed_.map(function(row) {
|
||||
return row.trim();
|
||||
return row.text.trim();
|
||||
}).join('\n')
|
||||
.replace(/^\n+|\n+$/g, '');
|
||||
|
||||
|
@ -2316,7 +2405,7 @@ QUnit.test('reset works', function(assert) {
|
|||
cea608Stream.reset();
|
||||
buffer = cea608Stream.displayed_
|
||||
.map(function(row) {
|
||||
return row.trim();
|
||||
return row.text.trim();
|
||||
})
|
||||
.join('\n')
|
||||
.replace(/^\n+|\n+$/g, '');
|
||||
|
@ -2348,12 +2437,16 @@ QUnit.test('paint-on mode', function(assert) {
|
|||
assert.deepEqual(captions[0], {
|
||||
startPts: 1000,
|
||||
endPts: 3000,
|
||||
text: 'hi',
|
||||
content: [{
|
||||
line: 15,
|
||||
position: 10,
|
||||
text: 'hi',
|
||||
}],
|
||||
stream: 'CC1'
|
||||
}, 'parsed the caption');
|
||||
});
|
||||
|
||||
QUnit.test('preserves newlines from PACs in paint-on mode', function(assert) {
|
||||
QUnit.test('generates correct text from PACs in paint-on mode', function(assert) {
|
||||
var captions = [];
|
||||
cea608Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
|
@ -2383,10 +2476,12 @@ QUnit.test('preserves newlines from PACs in paint-on mode', function(assert) {
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 1, 'caption emitted');
|
||||
assert.equal(captions[0].text, 'TEST\n\nSTRING\nDATA', 'Position PACs were converted to newlines');
|
||||
assert.equal(captions[0].content[0].text, 'TEST', 'first content text');
|
||||
assert.equal(captions[0].content[1].text, 'STRING', 'second content text');
|
||||
assert.equal(captions[0].content[2].text, 'DATA', 'third content text');
|
||||
});
|
||||
|
||||
QUnit.test('backspaces are reflected in the generated captions (paint-on)', function(assert) {
|
||||
QUnit.test('multiple caption texts are generated (paint-on)', function(assert) {
|
||||
var captions = [];
|
||||
cea608Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
|
@ -2410,7 +2505,113 @@ QUnit.test('backspaces are reflected in the generated captions (paint-on)', func
|
|||
].forEach(cea608Stream.push, cea608Stream);
|
||||
|
||||
assert.equal(captions.length, 1, 'detected a caption');
|
||||
assert.equal(captions[0].text, '310\n\n023', 'applied the backspaces');
|
||||
assert.equal(captions[0].content[0].text, '310', 'first caption text');
|
||||
assert.equal(captions[0].content[1].text, '023', 'second caption text');
|
||||
});
|
||||
|
||||
QUnit.test('PAC indent code increases the position', function(assert) {
|
||||
var captions = [];
|
||||
cea608Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
});
|
||||
|
||||
var packets = [
|
||||
// RCL, resume caption loading
|
||||
{ ccData: 0x1420, type: 0 },
|
||||
// PAC indent code representing 4 indentations.
|
||||
{ ccData: 5240, type: 0 },
|
||||
{ ccData: characters('te'), type: 0 },
|
||||
{ ccData: characters('st'), type: 0 },
|
||||
// EOC, End of Caption
|
||||
{ pts: 1 * 1000, ccData: 0x142f, type: 0 },
|
||||
// RCL, resume caption loading
|
||||
{ ccData: 0x1420, type: 0 },
|
||||
// EOC, End of Caption
|
||||
{ pts: 2 * 1000, ccData: 0x142f, type: 0 }
|
||||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].content[0].text, 'test', 'content text');
|
||||
assert.equal(captions[0].content[0].line, 15, 'positions the caption to the bottom of the screen');
|
||||
assert.equal(captions[0].content[0].position, 50, 'positions the caption to the right of the screen');
|
||||
});
|
||||
|
||||
QUnit.test('PAC offset code increases the position', function(assert) {
|
||||
var captions = [];
|
||||
cea608Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
});
|
||||
|
||||
var packets = [
|
||||
// RCL, resume caption loading
|
||||
{ ccData: 0x1420, type: 0 },
|
||||
// PAC: row 1, indent 0
|
||||
{ pts: 6750, ccData: 0x1150, type: 0 },
|
||||
// TO2 (tab offset 2 columns)
|
||||
{ pts: 6755, ccData: 0x1722, type: 0 },
|
||||
{ ccData: characters('te'), type: 0 },
|
||||
{ ccData: characters('st'), type: 0 },
|
||||
// EOC, End of Caption
|
||||
{ pts: 1 * 1000, ccData: 0x142f, type: 0 },
|
||||
// RCL, resume caption loading
|
||||
{ ccData: 0x1420, type: 0 },
|
||||
// EOC, End of Caption
|
||||
{ pts: 2 * 1000, ccData: 0x142f, type: 0 }
|
||||
];
|
||||
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].content[0].text, 'test', 'content text');
|
||||
assert.equal(captions[0].content[0].line, 1, 'positions the caption to the bottom of the screen');
|
||||
// Two tab offset columns adds 5 to the position (2 * 2.5)
|
||||
assert.equal(captions[0].content[0].position, 15, 'positions the caption to the right');
|
||||
});
|
||||
|
||||
QUnit.test('PAC row command ensures we have the correct line property for captions', function(assert) {
|
||||
var captions = [];
|
||||
cea608Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
});
|
||||
|
||||
var packets = [
|
||||
// RU2 (roll-up, 2 rows)
|
||||
{ pts: 6675, ccData: 0x1425, type: 0 },
|
||||
// CR (carriange return), flush nothing
|
||||
{ pts: 6675, ccData: 0x142d, type: 0 },
|
||||
// PAC: row 2, indent 0
|
||||
// This should ensure the captions are at the top of the screen.
|
||||
{ pts: 6675, ccData: 0x1170, type: 0 },
|
||||
// text: YEAR.
|
||||
{ pts: 6676, ccData: 0x5945, type: 0 },
|
||||
{ pts: 6676, ccData: 0x4152, type: 0 },
|
||||
{ pts: 6676, ccData: 0x2e00, type: 0 },
|
||||
// RU2 (roll-up, 2 rows)
|
||||
{ pts: 6677, ccData: 0x1425, type: 0 },
|
||||
// CR (carriange return), flush 1 row
|
||||
{ pts: 6677, ccData: 0x142d, type: 0 },
|
||||
// EDM (erase displayed memory), flush 2 displayed roll-up rows
|
||||
{ pts: 6697, ccData: 0x142c, type: 0 },
|
||||
// RDC (resume direct captioning), wipes memories, flushes nothing
|
||||
{ pts: 6749, ccData: 0x1429, type: 0 },
|
||||
// PAC: row 1, indent 0
|
||||
{ pts: 6750, ccData: 0x1150, type: 0 },
|
||||
// EOC, End of Caption
|
||||
{ pts: 1 * 1000, ccData: 0x142f, type: 0 },
|
||||
// RCL, resume caption loading
|
||||
{ ccData: 0x1420, type: 0 },
|
||||
// EOC, End of Caption
|
||||
{ pts: 2 * 1000, ccData: 0x142f, type: 0 }
|
||||
];
|
||||
|
||||
// First caption stream is at the second most bottom row.
|
||||
packets.forEach(cea608Stream.push, cea608Stream);
|
||||
assert.equal(captions[0].content[0].text, 'YEAR.', 'content text');
|
||||
assert.equal(captions[0].content[0].line, 2, 'positions the caption in the second most bottom row');
|
||||
assert.equal(captions[0].content[0].position, 10, 'position of the caption');
|
||||
|
||||
// Second caption stream is at the most bottom row.
|
||||
assert.equal(captions[1].content[0].text, 'YEAR.', 'content text');
|
||||
assert.equal(captions[1].content[0].line, 1, 'positions the caption in the most bottom row');
|
||||
assert.equal(captions[1].content[0].position, 10, 'position of the caption');
|
||||
});
|
||||
|
||||
QUnit.test('mix of all modes (extract from CNN)', function(assert) {
|
||||
|
@ -2606,45 +2807,101 @@ QUnit.test('mix of all modes (extract from CNN)', function(assert) {
|
|||
|
||||
assert.equal(captions.length, 7, 'detected 7 captions of varying types');
|
||||
assert.deepEqual(captions[0], {
|
||||
content: [{
|
||||
line: 2,
|
||||
position: 10,
|
||||
text: 'YEAR.',
|
||||
}],
|
||||
startPts: 6675,
|
||||
endPts: 6677,
|
||||
text: 'YEAR.',
|
||||
stream: 'CC1'
|
||||
}, 'parsed the 1st roll-up caption');
|
||||
assert.deepEqual(captions[1], {
|
||||
content: [
|
||||
{
|
||||
line: 1,
|
||||
position: 10,
|
||||
text: 'YEAR.',
|
||||
},
|
||||
{
|
||||
line: 2,
|
||||
position: 10,
|
||||
text: 'GO TO CNNHEROS.COM.',
|
||||
}
|
||||
],
|
||||
startPts: 6677,
|
||||
endPts: 6697,
|
||||
text: 'YEAR.\nGO TO CNNHEROS.COM.',
|
||||
stream: 'CC1'
|
||||
}, 'parsed the 2nd roll-up caption');
|
||||
assert.deepEqual(captions[2], {
|
||||
content: [
|
||||
{
|
||||
line: 1,
|
||||
position: 10,
|
||||
text: 'Did your Senator or Congressman',
|
||||
},
|
||||
{
|
||||
line: 2,
|
||||
position: 10,
|
||||
text: 'get elected by talking tough',
|
||||
}
|
||||
],
|
||||
startPts: 6749,
|
||||
endPts: 6781,
|
||||
text: 'Did your Senator or Congressman\nget elected by talking tough',
|
||||
stream: 'CC1'
|
||||
}, 'parsed the paint-on caption');
|
||||
assert.deepEqual(captions[3], {
|
||||
content: [{
|
||||
line: 1,
|
||||
position: 22.5,
|
||||
text: 'on the national debt?',
|
||||
}],
|
||||
startPts: 6782,
|
||||
endPts: 6797,
|
||||
text: 'on the national debt?',
|
||||
stream: 'CC1'
|
||||
}, 'parsed the 1st pop-on caption');
|
||||
assert.deepEqual(captions[4], {
|
||||
content: [
|
||||
{
|
||||
line: 1,
|
||||
position: 25,
|
||||
text: 'Will they stay true',
|
||||
},
|
||||
{
|
||||
line: 2,
|
||||
position: 30,
|
||||
text: 'to their words?',
|
||||
}
|
||||
],
|
||||
startPts: 6798,
|
||||
endPts: 6838,
|
||||
text: 'Will they stay true\nto their words?',
|
||||
stream: 'CC1'
|
||||
}, 'parsed the 2nd pop-on caption');
|
||||
assert.deepEqual(captions[5], {
|
||||
content: [{
|
||||
line: 2,
|
||||
position: 10,
|
||||
text: '>>> NO MORE SPECULATION, NO MORE',
|
||||
}],
|
||||
startPts: 6841,
|
||||
endPts: 6844,
|
||||
text: '>>> NO MORE SPECULATION, NO MORE',
|
||||
stream: 'CC1'
|
||||
}, 'parsed the 3rd roll-up caption');
|
||||
assert.deepEqual(captions[6], {
|
||||
content: [
|
||||
{
|
||||
line: 1,
|
||||
position: 10,
|
||||
text: '>>> NO MORE SPECULATION, NO MORE',
|
||||
},
|
||||
{
|
||||
line: 2,
|
||||
position: 10,
|
||||
text: 'RUMORS OR GUESSING GAMES.',
|
||||
}
|
||||
],
|
||||
startPts: 6844,
|
||||
endPts: 6846,
|
||||
text: '>>> NO MORE SPECULATION, NO MORE\nRUMORS OR GUESSING GAMES.',
|
||||
stream: 'CC1'
|
||||
}, 'parsed the 4th roll-up caption');
|
||||
|
||||
|
@ -2794,6 +3051,33 @@ QUnit.test('Decodes multibyte characters if valid encoding option is provided an
|
|||
}
|
||||
});
|
||||
|
||||
QUnit.test('Decodes multi-byte characters as unicode if no valid encoding option is provided', function(assert) {
|
||||
var captions = [];
|
||||
|
||||
cea708Stream = new m2ts.Cea708Stream({
|
||||
captionServices: {
|
||||
SERVICE1: {}
|
||||
}
|
||||
});
|
||||
|
||||
cea708Stream.on('data', function(caption) {
|
||||
captions.push(caption);
|
||||
});
|
||||
|
||||
cc708Korean.forEach(cea708Stream.push, cea708Stream);
|
||||
|
||||
cea708Stream.flushDisplayed(4721138662, cea708Stream.services[1]);
|
||||
|
||||
assert.equal(captions.length, 1, 'parsed single caption correctly');
|
||||
|
||||
assert.notOk(cea708Stream.services[1].textDecoder_, 'TextDecoder was not created');
|
||||
assert.equal(
|
||||
captions[0].text,
|
||||
'듏낡 ',
|
||||
'parsed multibyte characters correctly'
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('Creates TextDecoder only if valid encoding value is provided', function(assert) {
|
||||
var secondCea708Stream;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue