From 677d2d17a8ef9a30b0702ed01c8d6293a8a54d85 Mon Sep 17 00:00:00 2001 From: kkb912002 Date: Wed, 5 Mar 2025 14:37:18 +0900 Subject: [PATCH 1/5] add a missing param for startRecordingScreen --- lib/execute-method-map.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/execute-method-map.ts b/lib/execute-method-map.ts index 783ad4f1..f8687b36 100644 --- a/lib/execute-method-map.ts +++ b/lib/execute-method-map.ts @@ -6,6 +6,7 @@ export const executeMethodMap = { params: { optional: [ 'timeLimit', + 'videoFilter', 'fps', 'preset', 'captureCursor', From 5d1b7514ad74e632f6e4bccb32fd014c888de2a3 Mon Sep 17 00:00:00 2001 From: kkb912002 Date: Wed, 5 Mar 2025 14:39:27 +0900 Subject: [PATCH 2/5] support default recording command --- lib/commands/record-screen.js | 118 +++++++++++++++++++++++++++++++++- lib/driver.js | 2 + lib/execute-method-map.ts | 4 +- 3 files changed, 120 insertions(+), 4 deletions(-) diff --git a/lib/commands/record-screen.js b/lib/commands/record-screen.js index 7adc3fa7..0e6d5885 100644 --- a/lib/commands/record-screen.js +++ b/lib/commands/record-screen.js @@ -234,7 +234,7 @@ export class ScreenRecorder { * (`false`) or to start a new recording immediately and terminate the existing one if running (`true`). * @throws {Error} If screen recording has failed to start or is not supported on the device under test. */ -export async function startRecordingScreen ( +export async function windowsStartRecordingScreen ( timeLimit, videoFilter, fps, @@ -301,7 +301,7 @@ export async function startRecordingScreen ( * or the file content cannot be uploaded to the remote location * or screen recording is not supported on the device under test. */ -export async function stopRecordingScreen ( +export async function windowsStopRecordingScreen ( remotePath, user, pass, @@ -335,6 +335,120 @@ export async function stopRecordingScreen ( }); } +/** + * @typedef {Object} StartRecordingOptions + * + * @property {string} videoFilter - The video filter spec to apply for ffmpeg. + * See https://trac.ffmpeg.org/wiki/FilteringGuide for more details on the possible values. + * Example: Set it to `scale=ifnot(gte(iw\,1024)\,iw\,1024):-2` in order to limit the video width + * to 1024px. The height will be adjusted automatically to match the actual ratio. + * @property {number|string} fps [15] - The count of frames per second in the resulting video. + * The greater fps it has the bigger file size is. + * @property {string} preset [veryfast] - One of the supported encoding presets. Possible values are: + * - ultrafast + * - superfast + * - veryfast + * - faster + * - fast + * - medium + * - slow + * - slower + * - veryslow + * A preset is a collection of options that will provide a certain encoding speed to compression ratio. + * A slower preset will provide better compression (compression is quality per filesize). + * This means that, for example, if you target a certain file size or constant bit rate, you will achieve better + * quality with a slower preset. Read https://trac.ffmpeg.org/wiki/Encode/H.264 for more details. + * @property {boolean} captureCursor [false] - Whether to capture the mouse cursor while recording + * the screen + * @property {boolean} captureClicks [false] - Whether to capture mouse clicks while recording the + * screen + * @property {string} audioInput - If set then the given audio input will be used to record the computer audio + * along with the desktop video. The list of available devices could be retrieved using + * `ffmpeg -list_devices true -f dshow -i dummy` command. + * @property {string|number} timeLimit [600] - The maximum recording time, in seconds. The default + * value is 600 seconds (10 minutes). + * @property {boolean} forceRestart [true] - Whether to ignore the call if a screen recording is currently running + * (`false`) or to start a new recording immediately and terminate the existing one if running (`true`). + */ + +/** + * Record the display in background while the automated test is running. + * This method requires FFMPEG (https://www.ffmpeg.org/download.html) to be installed + * and present in PATH. + * The resulting video uses H264 codec and is ready to be played by media players built-in into web browsers. + * + * @param {StartRecordingOptions} options - The available options. + * @this {import('../driver').WindowsDriver} + * @throws {Error} If screen recording has failed to start or is not supported on the device under test. + */ +export async function startRecordingScreen(options) { + const { + timeLimit, + videoFilter, + fps, + preset, + captureCursor, + captureClicks, + audioInput, + forceRestart = true, + } = options ?? {}; + + await this.windowsStartRecordingScreen( + timeLimit, + videoFilter, + fps, + preset, + captureCursor, + captureClicks, + audioInput, + forceRestart + ); +} + +/** + * @typedef {Object} StopRecordingOptions + * + * @property {string} remotePath - The path to the remote location, where the resulting video should be uploaded. + * The following protocols are supported: http/https, ftp. + * Null or empty string value (the default setting) means the content of resulting + * file should be encoded as Base64 and passed as the endpoint response value. + * An exception will be thrown if the generated media file is too big to + * fit into the available process memory. + * @property {string} user - The name of the user for the remote authentication. + * @property {string} pass - The password for the remote authentication. + * @property {string} method - The http multipart upload method name. The 'PUT' one is used by default. + * @property {Object} headers - Additional headers mapping for multipart http(s) uploads + * @property {string} fileFieldName [file] - The name of the form field, where the file content BLOB should be stored for + * http(s) uploads + * @property {Object[]|[string, string][]} formFields - Additional form fields for multipart http(s) uploads + */ + +/** + * Stop recording the screen. + * If no screen recording has been started before then the method returns an empty string. + * + * @param {StopRecordingOptions} options - The available options. + * @returns {Promise} Base64-encoded content of the recorded media file if 'remotePath' + * parameter is falsy or an empty string. + * @this {import('../driver').WindowsDriver} + * @throws {Error} If there was an error while getting the name of a media file + * or the file content cannot be uploaded to the remote location + * or screen recording is not supported on the device under test. + */ +export async function stopRecordingScreen(options) { + const {remotePath, user, pass, method, headers, fileFieldName, formFields} = options ?? {}; + + return await this.windowsStopRecordingScreen( + remotePath, + user, + pass, + method, + headers, + fileFieldName, + formFields + ); +} + /** * @typedef {import('../driver').WindowsDriver} WindowsDriver */ diff --git a/lib/driver.js b/lib/driver.js index 622cfad8..ef82bb1f 100644 --- a/lib/driver.js +++ b/lib/driver.js @@ -204,6 +204,8 @@ export class WindowsDriver extends BaseDriver { execPowerShell = powershellCommands.execPowerShell; + windowsStartRecordingScreen = recordScreenCommands.windowsStartRecordingScreen; + windowsStopRecordingScreen = recordScreenCommands.windowsStopRecordingScreen; startRecordingScreen = recordScreenCommands.startRecordingScreen; stopRecordingScreen = recordScreenCommands.stopRecordingScreen; diff --git a/lib/execute-method-map.ts b/lib/execute-method-map.ts index f8687b36..5e7fca17 100644 --- a/lib/execute-method-map.ts +++ b/lib/execute-method-map.ts @@ -2,7 +2,7 @@ import { ExecuteMethodMap } from '@appium/types'; export const executeMethodMap = { 'windows: startRecordingScreen': { - command: 'startRecordingScreen', + command: 'windowsStartRecordingScreen', params: { optional: [ 'timeLimit', @@ -17,7 +17,7 @@ export const executeMethodMap = { }, }, 'windows: stopRecordingScreen': { - command: 'stopRecordingScreen', + command: 'windowsStopRecordingScreen', params: { optional: [ 'remotePath', From 08b43f649b1173f2193fe8d11741a178b4e30604 Mon Sep 17 00:00:00 2001 From: kkb912002 Date: Thu, 6 Mar 2025 07:17:15 +0900 Subject: [PATCH 3/5] fix typedefs and move to the end of thie file. --- lib/commands/record-screen.js | 97 +++++++++++++---------------------- 1 file changed, 37 insertions(+), 60 deletions(-) diff --git a/lib/commands/record-screen.js b/lib/commands/record-screen.js index 0e6d5885..702b55a2 100644 --- a/lib/commands/record-screen.js +++ b/lib/commands/record-screen.js @@ -335,53 +335,17 @@ export async function windowsStopRecordingScreen ( }); } -/** - * @typedef {Object} StartRecordingOptions - * - * @property {string} videoFilter - The video filter spec to apply for ffmpeg. - * See https://trac.ffmpeg.org/wiki/FilteringGuide for more details on the possible values. - * Example: Set it to `scale=ifnot(gte(iw\,1024)\,iw\,1024):-2` in order to limit the video width - * to 1024px. The height will be adjusted automatically to match the actual ratio. - * @property {number|string} fps [15] - The count of frames per second in the resulting video. - * The greater fps it has the bigger file size is. - * @property {string} preset [veryfast] - One of the supported encoding presets. Possible values are: - * - ultrafast - * - superfast - * - veryfast - * - faster - * - fast - * - medium - * - slow - * - slower - * - veryslow - * A preset is a collection of options that will provide a certain encoding speed to compression ratio. - * A slower preset will provide better compression (compression is quality per filesize). - * This means that, for example, if you target a certain file size or constant bit rate, you will achieve better - * quality with a slower preset. Read https://trac.ffmpeg.org/wiki/Encode/H.264 for more details. - * @property {boolean} captureCursor [false] - Whether to capture the mouse cursor while recording - * the screen - * @property {boolean} captureClicks [false] - Whether to capture mouse clicks while recording the - * screen - * @property {string} audioInput - If set then the given audio input will be used to record the computer audio - * along with the desktop video. The list of available devices could be retrieved using - * `ffmpeg -list_devices true -f dshow -i dummy` command. - * @property {string|number} timeLimit [600] - The maximum recording time, in seconds. The default - * value is 600 seconds (10 minutes). - * @property {boolean} forceRestart [true] - Whether to ignore the call if a screen recording is currently running - * (`false`) or to start a new recording immediately and terminate the existing one if running (`true`). - */ - /** * Record the display in background while the automated test is running. * This method requires FFMPEG (https://www.ffmpeg.org/download.html) to be installed * and present in PATH. * The resulting video uses H264 codec and is ready to be played by media players built-in into web browsers. * - * @param {StartRecordingOptions} options - The available options. + * @param {StartRecordingOptions} [options] - The available options. * @this {import('../driver').WindowsDriver} * @throws {Error} If screen recording has failed to start or is not supported on the device under test. */ -export async function startRecordingScreen(options) { +export async function startRecordingScreen(options = {}) { const { timeLimit, videoFilter, @@ -391,7 +355,7 @@ export async function startRecordingScreen(options) { captureClicks, audioInput, forceRestart = true, - } = options ?? {}; + } = options; await this.windowsStartRecordingScreen( timeLimit, @@ -405,29 +369,11 @@ export async function startRecordingScreen(options) { ); } -/** - * @typedef {Object} StopRecordingOptions - * - * @property {string} remotePath - The path to the remote location, where the resulting video should be uploaded. - * The following protocols are supported: http/https, ftp. - * Null or empty string value (the default setting) means the content of resulting - * file should be encoded as Base64 and passed as the endpoint response value. - * An exception will be thrown if the generated media file is too big to - * fit into the available process memory. - * @property {string} user - The name of the user for the remote authentication. - * @property {string} pass - The password for the remote authentication. - * @property {string} method - The http multipart upload method name. The 'PUT' one is used by default. - * @property {Object} headers - Additional headers mapping for multipart http(s) uploads - * @property {string} fileFieldName [file] - The name of the form field, where the file content BLOB should be stored for - * http(s) uploads - * @property {Object[]|[string, string][]} formFields - Additional form fields for multipart http(s) uploads - */ - /** * Stop recording the screen. * If no screen recording has been started before then the method returns an empty string. * - * @param {StopRecordingOptions} options - The available options. + * @param {StopRecordingOptions} [options] - The available options. * @returns {Promise} Base64-encoded content of the recorded media file if 'remotePath' * parameter is falsy or an empty string. * @this {import('../driver').WindowsDriver} @@ -435,8 +381,8 @@ export async function startRecordingScreen(options) { * or the file content cannot be uploaded to the remote location * or screen recording is not supported on the device under test. */ -export async function stopRecordingScreen(options) { - const {remotePath, user, pass, method, headers, fileFieldName, formFields} = options ?? {}; +export async function stopRecordingScreen(options = {}) { + const {remotePath, user, pass, method, headers, fileFieldName, formFields} = options; return await this.windowsStopRecordingScreen( remotePath, @@ -452,3 +398,34 @@ export async function stopRecordingScreen(options) { /** * @typedef {import('../driver').WindowsDriver} WindowsDriver */ + +/** + * For detailed explanations of each property, + * please refer to the parameters of the `windowsStartRecordingScreen` function. + * + * @typedef {Object} StartRecordingOptions + * + * @property {string} [videoFilter] + * @property {number|string} [fps=15] + * @property {string} [preset='veryfast'] + * @property {boolean} [captureCursor=false] + * @property {boolean} [captureClicks=false] + * @property {string} [audioInput] + * @property {string|number} [timeLimit=600] + * @property {boolean} [forceRestart=true] + */ + +/** + * For detailed explanations of each property, + * please refer to the parameters of the `windowsStopRecordingScreen` function. + * + * @typedef {Object} StopRecordingOptions + * + * @property {string} [remotePath] + * @property {string} [user] + * @property {string} [pass] + * @property {string} [method] + * @property {Object} [headers] + * @property {string} [fileFieldName='file'] + * @property {Object[]|[string, string][]} [formFields] + */ \ No newline at end of file From 9b9ac730ee88cda53e46925de6ad074bdb7233a2 Mon Sep 17 00:00:00 2001 From: kkb912002 Date: Thu, 6 Mar 2025 07:21:39 +0900 Subject: [PATCH 4/5] remove trailing spaces --- lib/commands/record-screen.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/commands/record-screen.js b/lib/commands/record-screen.js index 702b55a2..2863b731 100644 --- a/lib/commands/record-screen.js +++ b/lib/commands/record-screen.js @@ -402,7 +402,7 @@ export async function stopRecordingScreen(options = {}) { /** * For detailed explanations of each property, * please refer to the parameters of the `windowsStartRecordingScreen` function. - * + * * @typedef {Object} StartRecordingOptions * * @property {string} [videoFilter] @@ -418,7 +418,7 @@ export async function stopRecordingScreen(options = {}) { /** * For detailed explanations of each property, * please refer to the parameters of the `windowsStopRecordingScreen` function. - * + * * @typedef {Object} StopRecordingOptions * * @property {string} [remotePath] From a66733dc9a81d8c8ce32b0bda737e1f9f11c0a05 Mon Sep 17 00:00:00 2001 From: kkb912002 Date: Thu, 6 Mar 2025 17:11:22 +0900 Subject: [PATCH 5/5] add linkcode to comment. --- lib/commands/record-screen.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/commands/record-screen.js b/lib/commands/record-screen.js index 2863b731..cf9e9ac8 100644 --- a/lib/commands/record-screen.js +++ b/lib/commands/record-screen.js @@ -401,7 +401,7 @@ export async function stopRecordingScreen(options = {}) { /** * For detailed explanations of each property, - * please refer to the parameters of the `windowsStartRecordingScreen` function. + * please refer to the parameters of the {@linkcode windowsStartRecordingScreen} function. * * @typedef {Object} StartRecordingOptions * @@ -417,7 +417,7 @@ export async function stopRecordingScreen(options = {}) { /** * For detailed explanations of each property, - * please refer to the parameters of the `windowsStopRecordingScreen` function. + * please refer to the parameters of the {@linkcode windowsStopRecordingScreen} function. * * @typedef {Object} StopRecordingOptions *