-
-
Notifications
You must be signed in to change notification settings - Fork 130
add mjpeg stream helper class to basedriver #230
Conversation
lib/basedriver/mjpeg.js
Outdated
* @returns {string} | ||
*/ | ||
get lastChunkBase64 () { | ||
if (!this.lastChunk) { |
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.
Ternary operator might be shorter here
lib/basedriver/mjpeg.js
Outdated
/** | ||
* Start reading the MJpeg stream and storing the last image | ||
*/ | ||
start () { |
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.
why not async?
// just send the same jpeg over and over | ||
for (let i = 0; i < times; i++) { | ||
await B.delay(intMs); | ||
mJpegReqHandler._write(jpg, null, () => {}); |
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.
there is also _.noop helper
We probably would need some fast PNG->JPEG converter here as well |
For now my thought is if someone uses this, they know they will get jpeg formatted screenshots out of appium instead of png. |
Selenium's getScreenshot always returns images in PNG format. There are no other endpoints, which allow to get JPEG directly. That is why I suppose we need to do the conversion on Appium side |
lib/basedriver/mjpeg.js
Outdated
* @returns {string} | ||
*/ | ||
get lastChunkBase64 () { | ||
return this.lastChunk ? this.lastChunk.toString('base64') : null; |
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.
_.isBuffer(lastChunk) ?
lib/basedriver/mjpeg.js
Outdated
/** | ||
* Start reading the MJpeg stream and storing the last image | ||
*/ | ||
async start () { |
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.
👍
lib/basedriver/mjpeg.js
Outdated
* the HTTP request itself. Then reset the state. | ||
*/ | ||
stop () { | ||
if (this.consumer) { |
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 (!this.consumer) return
.pipe(this.consumer) // allow chunking and transforming of jpeg data | ||
.pipe(this); // send the actual jpegs to ourself | ||
|
||
await startPromise; |
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.
should it block till the first image is received?
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.
there is no last image, so that's not possible.
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.
I mean this might block forever if the server does not produce any data
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.
oh right. that would be an error. probably we should have a timeout and if the timeout gets hit, throw an error
lib/basedriver/mjpeg.js
Outdated
* Reset internal state | ||
*/ | ||
clear () { | ||
this.didStart = false; |
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.
is this used?
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.
nope! will remove
@mykola-mokhnach @imurchie what do you think, should this be a part of appium-support instead? now that it is just a class which can be used, but not tied to the driver code itself. |
If the class has no direct dependencies on base driver then yes, it would be better to keep it in appium-support |
lib/basedriver/mjpeg.js
Outdated
|
||
// start a timeout so that if the server does not return data, we don't | ||
// block forever. | ||
setTimeout(() => { |
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.
I think bluebird promises already have the standard .timeout method
this.lastChunk.toString('base64') : | ||
null; | ||
} | ||
|
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.
extra empty line here
closing, gonna move to appium-support |
There is this "standard" of sorts called MJPEG, which allows for streaming of images over HTTP. Some users of Appium have MJPEG servers connected to the devices they use with Appium, which deliver relatively high-framerate images off the device. If this is the case, why not just use it for screenshots as well and bypass the sometimes time-consuming Appium-internal screenshot commands?
MJPEG is a sort-of "push" mechanism, so in this PR I just provide a class which maintains a reference to the last-pushed image, which would then be available to any driver that wants it. I'll start the driver PRs soon, but the basic idea is that this will be behind a capability, which if turned on will just send back the last-received image immediately upon screenshot request. Something like this: