-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support of fontSize in percentages and cell resolution unit for TTML captions #2442
Add support of fontSize in percentages and cell resolution unit for TTML captions #2442
Conversation
lib/text/cue.js
Outdated
* @const | ||
* @export | ||
*/ | ||
shaka.text.Cue.cellResolution = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The enums below and above are possible options for each field. This is a set of defaults. I would prefer you move it to the initialization of the member:
this.cellResolution = [32, 15]; // columns, rows
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
lib/text/ttml_text_parser.js
Outdated
// If not specified, the number of columns and rows must be considered | ||
// to be 32 and 15 respectively |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've already defined a default in the Cue constructor. Why duplicate it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree,
changed the logic, so now cue.cellResolution default value will be replaced only if ttp:cellResolution was presented in ttml
test/text/ttml_text_parser_unit.js
Outdated
cellResolution: [ | ||
Cue.cellResolution.COLUMNS, | ||
Cue.cellResolution.ROWS, | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it doesn't matter what the cellResolution is in this output cue (since it's not using c units), you can omit this field. verifyHelper below uses jasmine.objectContaining() to match, so any field you don't specify in the expectation won't count.
In fact, it seems that this test case doesn't have much to do with cellResolution at all, so maybe you could omit it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test was added to check that Cue has default cellResolution when ttp:cellResolution was not presented in ttml
I guess it would be nice to leave this check
test/ui/text_displayer_unit.js
Outdated
@@ -39,15 +41,20 @@ describe('UITextDisplayer', () => { | |||
} | |||
|
|||
|
|||
beforeAll(() => { | |||
beforeEach(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The addition of video elements to the DOM should be beforeAll instead of beforeEach.
You could move textDisplayer setup specifically to beforeEach and leave the rest in beforeAll.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, you are right, thanks
was fixed
jasmine.objectContaining({'font-size': expectedFontSize})); | ||
}); | ||
|
||
it('correctly displays styles for percentages units', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for adding these tests!
ui/text_displayer.js
Outdated
@@ -268,11 +268,15 @@ shaka.ui.TextDisplayer = class { | |||
captionsStyle.margin = '0'; | |||
} | |||
|
|||
const {convertLengthValue_} = shaka.ui.TextDisplayer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You only call this once. Just refer to it directly with its full name at the call site.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
ui/text_displayer.js
Outdated
} | ||
|
||
/** | ||
* Converts length value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Converts length value" returning "string" is not enough information for the reader. What format is the string? What sort of conversion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the description was updated,
could you please take a look if I need to add more details
ui/text_displayer.js
Outdated
static getLengthValueInfo_(lengthValue) { | ||
const matches = new RegExp(/(\d*\.?\d+)([a-z]+|%+)/).exec(lengthValue); | ||
|
||
if (!matches ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style nit: remove extra space inside parens
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
ui/text_displayer.js
Outdated
* | ||
* @private | ||
* */ | ||
static getComputedValue_(value, cue, videoContainer) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"computed value" is a bit vague. This method actually does something very specific: computes an absolute value in pixels based on cell and video size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was renamed to getAbsoluteLengthInPixels_
and added the description for this method,
could you please take a look if I need to add more details
thanks
@theodab @joeyparrish , thank you for the review and quick feedback! The comments were fixed. Could you please take a look and let me know if there is anything else that needs to be done. |
All tests passed! |
Whoops, I accidentally started an extraneous test run. Sorry about that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great overall. Just a few things I'd like you to change. Thanks!
externs/shaka/text.js
Outdated
* The number of horizontal and vertical cells into which | ||
* the Root Container Region area is divided | ||
* | ||
* @typedef {{ columns: number, rows: number }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looked different from what we would normally use, so I checked. It seems that with this annotation, the compiler doesn't enforce the type correctly. What you want is @type {{ columns: number, rows: number }}
instead.
A typedef in Closure Compiler is used for creating a new type, but not for assigning a type to a member. I know the compiler can be arcane, so I'm sorry for the trouble.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the explanation!
done
lib/text/ttml_text_parser.js
Outdated
@@ -239,12 +245,13 @@ shaka.text.TtmlTextParser = class { | |||
* @param {!Array.<!shaka.text.CueRegion>} cueRegions | |||
* @param {boolean} whitespaceTrim | |||
* @param {boolean} isNested | |||
* @param {?Object} cellResolution |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Object" is too general a type. Please use a record type like you did in Cue:
{?{columns: number, rows: number}}
, so that the compiler can catch a caller using the wrong fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lib/text/ttml_text_parser.js
Outdated
@@ -334,6 +342,10 @@ shaka.text.TtmlTextParser = class { | |||
const cue = new shaka.text.Cue(start, end, payload); | |||
cue.nestedCues = nestedCues; | |||
|
|||
if (cellResolution) { | |||
cue.cellResolution = Object.assign({}, cellResolution); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need Object.assign. The provided value won't be changed by the method that generated it, and you'll preserve type info in the compiler by assigning it directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed Object.assign
* @private | ||
*/ | ||
static getCellResolution_(cellResolution) { | ||
const matches = /^(\d+) (\d+)$/.exec(cellResolution); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cellResolution can be null, and this would convert null
into the string "null"
.
While that shouldn't cause any false positives, it may be best to handle !cellResolution
explicitly, either here or when the attribute is extracted from the TTML.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,
added check to getCellResolution_
method
test/ui/text_displayer_unit.js
Outdated
textDisplayer = new shaka.ui.TextDisplayer(video, videoContainer); | ||
}); | ||
|
||
afterEach(() => { | ||
textDisplayer.destroy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
destroy() is async, so please make this callback async and await the results of destroy().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, I can miss something, but as I see TextDisplayer destroy
method is not async
https://github.com/google/shaka-player/blob/ea0131dc80483c7df2c9ec5c9ed62fbe560f37c3/ui/text_displayer.js#L67-L84
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That implementation is not async today, but the underlying interfaces shaka.extern.TextDisplayer
and shaka.util.IDestroyable
are async and return a Promise. In our codebase, any destroy()
is async, and any release()
is immediate.
It would be possible for us to add async steps to destroy()
in shaka.ui.TextDisplayer
at any time, and the tests should honor the contract of that API and use await.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for such a detailed explanation, now I've got it
done
ui/text_displayer.js
Outdated
*/ | ||
static convertLengthValue_(lengthValue, cue, videoContainer) { | ||
const lengthValueInfo = | ||
shaka.ui.TextDisplayer.getLengthValueInfo_(lengthValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: indent +2 spaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, not fully understood
should I remove 2 spaces to be like this
const lengthValueInfo =
shaka.ui.TextDisplayer.getLengthValueInfo_(lengthValue);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I meant +2 more, for a total of 4 more than the previous line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
ui/text_displayer.js
Outdated
case '%': | ||
return shaka.ui.TextDisplayer.getAbsoluteLengthInPixels_( | ||
value / 100, cue, videoContainer | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style nit: move to previous line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
ui/text_displayer.js
Outdated
case 'c': | ||
return shaka.ui.TextDisplayer.getAbsoluteLengthInPixels_( | ||
value, cue, videoContainer | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style nit: move to previous line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! Thanks for all your hard work.
All tests passed! |
Unfortunately, this change did not cherry-pick cleanly to v2.5.x, and so will not be in an official release until v2.6.0. |
Scope of PR:
Note:
*From w3c spec:
Percentages: if not region element, then relative to the parent element's computed font size; otherwise, relative to the Computed Cell Size.
Currently will be calculated relative to the Computed Cell Size.
Spec:
tts:fontSize - https://www.w3.org/TR/ttml1/#style-attribute-fontSize
ttp:cellResolution - https://www.w3.org/TR/ttml1/#parameter-attribute-cellResolution
- https://www.w3.org/TR/ttml1/#style-value-length
Useful links that helped during development and documentation investigation:
https://www.w3.org/TR/ttml1/
http://sandflow.com/imsc1_1/ - IMSC1 Renderer
https://trac.videolan.org/vlc/ticket/18347
Sample TTML that can be used for testing:
ttml-captions-test.zip
Closes #2403