How to use recorder.cleanup method in Appium Xcuitest Driver

Best JavaScript code snippet using appium-xcuitest-driver

recordscreen.js

Source:recordscreen.js Github

copy

Full Screen

1import { fs, tempDir, logger } from 'appium-support';2import { SubProcess } from 'teen_process';3import log from '../logger';4import { encodeBase64OrUpload } from '../utils';5import iProxy from '../wda/iproxy';6let commands = {};7const MAX_RECORDING_TIME_SEC = 60 * 30;8const DEFAULT_RECORDING_TIME_SEC = 60 * 3;9const DEFAULT_MJPEG_SERVER_PORT = 9100;10const MP4_EXT = '.mp4';11const DEFAULT_FPS = 10;12const FFMPEG_BINARY = 'ffmpeg';13const ffmpegLogger = logger.getLogger(FFMPEG_BINARY);14class ScreenRecorder {15 constructor (udid, videoPath, opts = {}) {16 this.videoPath = videoPath;17 this.opts = opts;18 this.udid = udid;19 this.mainProcess = null;20 this.iproxy = null;21 this.timeoutHandler = null;22 }23 async start (timeoutMs) {24 try {25 await fs.which(FFMPEG_BINARY);26 } catch (err) {27 throw new Error(`'${FFMPEG_BINARY}' binary is not found in PATH. Install it using 'brew install ffmpeg'. ` +28 `Check https://www.ffmpeg.org/download.html for more details.`);29 }30 const localPort = this.opts.remotePort;31 if (this.opts.usePortForwarding) {32 await this.startIproxy(localPort);33 }34 const args = [35 '-f', 'mjpeg',36 '-r', this.opts.videoFps,37 '-i', `http://localhost:${localPort}`,38 '-vcodec', 'mjpeg',39 '-y', this.videoPath,40 ];41 this.mainProcess = new SubProcess(FFMPEG_BINARY, args);42 this.mainProcess.on('output', (stdout, stderr) => {43 if (stderr && !stderr.includes('frame=')) {44 ffmpegLogger.info(`${stderr}`);45 }46 });47 // Give ffmpeg some time for init48 await this.mainProcess.start(5000);49 log.info(`Starting screen capture on the device '${this.udid}' with command: '${FFMPEG_BINARY} ${args.join(' ')}'. ` +50 `Will timeout in ${timeoutMs}ms`);51 this.timeoutHandler = setTimeout(async () => {52 if (!await this.interrupt()) {53 log.warn(`Cannot finish the active screen recording on the device '${this.udid}' after ${timeoutMs}ms timeout`);54 }55 }, timeoutMs);56 }57 async startIproxy (localPort) {58 this.iproxy = new iProxy(this.udid, localPort, this.opts.remotePort);59 try {60 await this.iproxy.start();61 } catch (err) {62 log.warn(`Cannot start iproxy. Assuming it is already forwarding the remote port ${this.opts.remotePort} to ${localPort} ` +63 `for the device ${this.udid}. Set the custom value to 'mjpegServerPort' capability if this is an undesired behavior. ` +64 `Original error: ${err.message}`);65 this.iproxy = null;66 }67 }68 async stopIproxy () {69 if (!this.iproxy) {70 return;71 }72 const quitPromise = this.iproxy.quit();73 this.iproxy = null;74 try {75 await quitPromise;76 } catch (err) {77 log.warn(`Cannot stop iproxy. Original error: ${err.message}`);78 }79 }80 async interrupt (force = false) {81 let result = true;82 if (this.timeoutHandler) {83 clearTimeout(this.timeoutHandler);84 this.timeoutHandler = null;85 }86 if (this.mainProcess && this.mainProcess.isRunning) {87 const interruptPromise = this.mainProcess.stop(force ? 'SIGTERM' : 'SIGINT');88 this.mainProcess = null;89 try {90 await interruptPromise;91 } catch (e) {92 log.warn(`Cannot ${force ? 'terminate' : 'interrupt'} ${FFMPEG_BINARY}. ` +93 `Original error: ${e.message}`);94 result = false;95 }96 }97 if (this.opts.usePortForwarding) {98 await this.stopIproxy();99 }100 return result;101 }102 async finish () {103 await this.interrupt();104 return this.videoPath;105 }106 async cleanup () {107 if (await fs.exists(this.videoPath)) {108 await fs.rimraf(this.videoPath);109 }110 }111}112/**113 * @typedef {Object} StartRecordingOptions114 *115 * @property {?string} remotePath - The path to the remote location, where the resulting video should be uploaded.116 * The following protocols are supported: http/https, ftp.117 * Null or empty string value (the default setting) means the content of resulting118 * file should be encoded as Base64 and passed as the endpount response value.119 * An exception will be thrown if the generated media file is too big to120 * fit into the available process memory.121 * This option only has an effect if there is screen recording process in progreess122 * and `forceRestart` parameter is not set to `true`.123 * @property {?string} user - The name of the user for the remote authentication. Only works if `remotePath` is provided.124 * @property {?string} pass - The password for the remote authentication. Only works if `remotePath` is provided.125 * @property {?string} method - The http multipart upload method name. The 'PUT' one is used by default.126 * Only works if `remotePath` is provided.127 * @property {?string} videoType - The format of the screen capture to be recorded.128 * Available formats: "h264", "mp4" or "fmp4". Default is "mp4".129 * @property {?string} videoQuality - The video encoding quality (low, medium, high, photo - defaults to medium).130 * @property {?string} videoFps - The Frames Per Second rate of the recorded video. Change this value if the resulting video131 * is too slow or too fast. Defaults to 10.132 * @property {?boolean} forceRestart - Whether to try to catch and upload/return the currently running screen recording133 * (`false`, the default setting) or ignore the result of it and start a new recording134 * immediately.135 * @property {?string|number} timeLimit - The maximum recording time, in seconds.136 * The default value is 180, the maximum value is 600 (10 minutes).137 */138/**139 * Record the display of devices running iOS Simulator since Xcode 8.3 or real devices since iOS 8140 * (ios-minicap utility is required: https://github.com/openstf/ios-minicap).141 * It records screen activity to a MPEG-4 file. Audio is not recorded with the video file.142 * If screen recording has been already started then the command will stop it forcefully and start a new one.143 * The previously recorded video file will be deleted.144 *145 * @param {?StartRecordingOptions} options - The available options.146 * @returns {string} Base64-encoded content of the recorded media file if147 * any screen recording is currently running or an empty string.148 * @throws {Error} If screen recording has failed to start.149 */150commands.startRecordingScreen = async function (options = {}) {151 const {152 videoType,153 timeLimit = DEFAULT_RECORDING_TIME_SEC,154 videoQuality = 'medium',155 videoFps = DEFAULT_FPS,156 forceRestart,157 } = options;158 let result = '';159 if (!forceRestart) {160 log.info(`Checking if there is/was a previous screen recording. ` +161 `Set 'forceRestart' option to 'true' if you'd like to skip this step.`);162 result = await this.stopRecordingScreen(options);163 }164 const videoPath = await tempDir.path({165 prefix: `appium_${Math.random().toString(16).substring(2, 8)}`,166 suffix: MP4_EXT,167 });168 const screenRecorder = new ScreenRecorder(this.opts.device.udid, videoPath, {169 // TODO: Apply type and quality options170 videoType,171 videoQuality,172 videoFps: videoFps || DEFAULT_FPS,173 remotePort: this.opts.mjpegServerPort || DEFAULT_MJPEG_SERVER_PORT,174 usePortForwarding: this.isRealDevice(),175 });176 if (!await screenRecorder.interrupt(true)) {177 log.errorAndThrow('Unable to stop screen recording process');178 }179 if (this._recentScreenRecorder) {180 await this._recentScreenRecorder.cleanup();181 this._recentScreenRecorder = null;182 }183 const timeoutSeconds = parseFloat(timeLimit);184 if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_RECORDING_TIME_SEC || timeoutSeconds <= 0) {185 log.errorAndThrow(`The timeLimit value must be in range [1, ${MAX_RECORDING_TIME_SEC}] seconds. ` +186 `The value of '${timeLimit}' has been passed instead.`);187 }188 try {189 await screenRecorder.start(timeoutSeconds * 1000);190 } catch (e) {191 await screenRecorder.interrupt(true);192 await screenRecorder.cleanup();193 throw e;194 }195 this._recentScreenRecorder = screenRecorder;196 return result;197};198/**199 * @typedef {Object} StopRecordingOptions200 *201 * @property {?string} remotePath - The path to the remote location, where the resulting video should be uploaded.202 * The following protocols are supported: http/https, ftp.203 * Null or empty string value (the default setting) means the content of resulting204 * file should be encoded as Base64 and passed as the endpount response value.205 * An exception will be thrown if the generated media file is too big to206 * fit into the available process memory.207 * @property {?string} user - The name of the user for the remote authentication. Only works if `remotePath` is provided.208 * @property {?string} pass - The password for the remote authentication. Only works if `remotePath` is provided.209 * @property {?string} method - The http multipart upload method name. The 'PUT' one is used by default.210 * Only works if `remotePath` is provided.211 */212/**213 * Stop recording the screen. If no screen recording process is running then214 * the endpoint will try to get the recently recorded file.215 * If no previously recorded file is found and no active screen recording216 * processes are running then the method returns an empty string.217 *218 * @param {?StopRecordingOptions} options - The available options.219 * @returns {string} Base64-encoded content of the recorded media file if 'remotePath'220 * parameter is empty or null or an empty string.221 * @throws {Error} If there was an error while getting the name of a media file222 * or the file content cannot be uploaded to the remote location.223 */224commands.stopRecordingScreen = async function (options = {}) {225 const {226 remotePath,227 user,228 pass,229 method,230 } = options;231 if (!this._recentScreenRecorder) {232 log.info('Screen recording is not running. There is nothing to stop.');233 return '';234 }235 try {236 const videoPath = await this._recentScreenRecorder.finish();237 if (!await fs.exists(videoPath)) {238 log.errorAndThrow(`The screen recorder utility has failed ` +239 `to store the actual screen recording at '${videoPath}'`);240 }241 return await encodeBase64OrUpload(videoPath, remotePath, {242 user,243 pass,244 method245 });246 } finally {247 await this._recentScreenRecorder.interrupt(true);248 await this._recentScreenRecorder.cleanup();249 this._recentScreenRecorder = null;250 }251};252export { commands };...

Full Screen

Full Screen

record-audio.js

Source:record-audio.js Github

copy

Full Screen

1import { fs, tempDir, logger, util } from '@appium/support';2import { SubProcess } from 'teen_process';3import { encodeBase64OrUpload } from '../utils';4import { waitForCondition } from 'asyncbox';5const commands = {};6const AUDIO_RECORD_FEAT_NAME = 'audio_record';7const MAX_RECORDING_TIME_SEC = 60 * 60 * 12;8const DEFAULT_RECORDING_TIME_SEC = 60 * 3;9const PROCESS_STARTUP_TIMEOUT_MS = 5000;10const DEFAULT_SOURCE = 'avfoundation';11const DEFAULT_BITRATE = '128k';12const DEFAULT_CODEC = 'aac';13const DEFAULT_CHANNELS = 2;14const DEFAULT_RATE = 44100;15const DEFAULT_EXT = '.mp4';16const FFMPEG_BINARY = 'ffmpeg';17const ffmpegLogger = logger.getLogger(FFMPEG_BINARY);18class AudioRecorder {19 constructor (input, log, audioPath, opts = {}) {20 this.input = input;21 this.log = log;22 this.audioPath = audioPath;23 this.opts = opts;24 this.mainProcess = null;25 }26 async start (timeoutSeconds) {27 try {28 await fs.which(FFMPEG_BINARY);29 } catch (err) {30 throw new Error(`'${FFMPEG_BINARY}' binary is not found in PATH. Install it using 'brew install ffmpeg'. ` +31 `Check https://www.ffmpeg.org/download.html for more details.`);32 }33 const {34 audioSource = DEFAULT_SOURCE,35 audioCodec,36 audioBitrate,37 audioChannels,38 audioRate,39 } = this.opts;40 const args = [41 '-t', `${timeoutSeconds}`,42 '-f', audioSource,43 '-i', this.input,44 '-c:a', audioCodec,45 '-b:a', audioBitrate,46 '-ac', `${audioChannels}`,47 '-ar', `${audioRate}`,48 this.audioPath,49 ];50 this.mainProcess = new SubProcess(FFMPEG_BINARY, args);51 let isCaptureStarted = false;52 this.mainProcess.on('output', (stdout, stderr) => {53 if (stderr) {54 if (stderr.trim().startsWith('size=')) {55 if (!isCaptureStarted) {56 isCaptureStarted = true;57 }58 } else {59 ffmpegLogger.info(`${stderr}`);60 }61 }62 });63 await this.mainProcess.start(0);64 try {65 await waitForCondition(() => isCaptureStarted, {66 waitMs: PROCESS_STARTUP_TIMEOUT_MS,67 intervalMs: 300,68 });69 } catch (e) {70 this.log.warn(`Audio recording process did not start within ${PROCESS_STARTUP_TIMEOUT_MS}ms. Continuing anyway`);71 }72 if (!this.mainProcess.isRunning) {73 this.mainProcess = null;74 throw new Error(`The audio recording process '${FFMPEG_BINARY}' died unexpectedly. ` +75 `Check server logs for more details`);76 }77 this.log.info(`Starting capture on audio input '${this.input}' with command: '${util.quote([FFMPEG_BINARY, ...args])}'. ` +78 `Will timeout in ${timeoutSeconds}s`);79 this.mainProcess.once('exit', (code, signal) => {80 // ffmpeg returns code 255 if SIGINT arrives81 if ([0, 255].includes(code)) {82 this.log.info(`The recording session on audio input '${this.input}' has been finished`);83 } else {84 this.log.debug(`The recording session on audio input '${this.input}' has exited ` +85 `with code ${code}, signal ${signal}`);86 }87 });88 }89 isRecording () {90 return !!(this.mainProcess?.isRunning);91 }92 async interrupt (force = false) {93 if (this.isRecording()) {94 const interruptPromise = this.mainProcess.stop(force ? 'SIGTERM' : 'SIGINT');95 this.mainProcess = null;96 try {97 await interruptPromise;98 } catch (e) {99 this.log.warn(`Cannot ${force ? 'terminate' : 'interrupt'} ${FFMPEG_BINARY}. ` +100 `Original error: ${e.message}`);101 return false;102 }103 }104 return true;105 }106 async finish () {107 await this.interrupt();108 return this.audioPath;109 }110 async cleanup () {111 if (await fs.exists(this.audioPath)) {112 await fs.rimraf(this.audioPath);113 }114 }115}116/**117 * @typedef {Object} StartRecordingOptions118 *119 * @property {!string} audioInput - The name of the corresponding audio input device to use for the120 * capture. The full list of capture devices could be shown using `ffmpeg -f avfoundation -list_devices true -i ""`121 * Terminal command.122 * @property {?string} audioCodec [aac] - The name of the audio codec. The Advanced Audio Codec is used by default.123 * @property {?string} audioBitrate [128k] - The bitrate of the resulting audio stream. 128k by default.124 * @property {?string|number} audioChannels [2] - The count of audio channels in the resulting stream. Setting it to `1`125 * will create a single channel (mono) audio stream.126 * @property {?string|number} audioRate [44100] - The sampling rate of the resulting audio stream.127 * @property {?string|number} timeLimit [180] - The maximum recording time, in seconds.128 * The default value is 180, the maximum value is 43200 (12 hours).129 * @property {?boolean} forceRestart [false] - Whether to restart audio capture process forcefully when130 * startRecordingAudio is called (`true`) or ignore the call until the current audio recording is completed.131 */132/**133 * Records the given hardware audio input into an .mp4 file.134 *135 * @param {?StartRecordingOptions} options - The available options.136 * @throws {Error} If audio recording has failed to start.137 */138commands.startAudioRecording = async function startAudioRecording (options = {}) {139 if (!this.isFeatureEnabled(AUDIO_RECORD_FEAT_NAME)) {140 this.log.errorAndThrow(`Audio capture feature must be enabled on the server side. ` +141 `Please set '--relaxed-security' or '--allow-insecure' with '${AUDIO_RECORD_FEAT_NAME}' option. ` +142 `Read https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/security.md for more details.`);143 }144 const {145 timeLimit = DEFAULT_RECORDING_TIME_SEC,146 audioInput,147 // Undocumented feature148 audioSource,149 audioCodec = DEFAULT_CODEC,150 audioBitrate = DEFAULT_BITRATE,151 audioChannels = DEFAULT_CHANNELS,152 audioRate = DEFAULT_RATE,153 forceRestart,154 } = options;155 if (!audioInput) {156 this.log.errorAndThrow(`The mandatory audioInput option is not provided. Please set it ` +157 `to a correct value (e. g. ':1'). Use 'ffmpeg -f avfoundation -list_devices true -i ""' ` +158 `command to list available input sources`);159 }160 if (this._audioRecorder?.isRecording()) {161 this.log.info(`There is an active audio recording process`);162 if (forceRestart) {163 this.log.info(`Stopping it because 'forceRestart' option is set to true`);164 await this._audioRecorder.interrupt(true);165 } else {166 this.log.info(`Doing nothing. ` +167 `Set 'forceRestart' option to true if you'd like to start a new audio recording session`);168 return;169 }170 }171 if (this._audioRecorder) {172 await this._audioRecorder.cleanup();173 this._audioRecorder = null;174 }175 const audioPath = await tempDir.path({176 prefix: `appium_${util.uuidV4().substring(0, 8)}`,177 suffix: DEFAULT_EXT,178 });179 const audioRecorder = new AudioRecorder(audioInput, this.log, audioPath, {180 audioSource,181 audioCodec,182 audioBitrate,183 audioChannels,184 audioRate,185 });186 const timeoutSeconds = parseInt(timeLimit, 10);187 if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_RECORDING_TIME_SEC || timeoutSeconds <= 0) {188 this.log.errorAndThrow(`The timeLimit value must be in range [1, ${MAX_RECORDING_TIME_SEC}] seconds. ` +189 `The value of '${timeLimit}' has been passed instead.`);190 }191 try {192 await audioRecorder.start(timeoutSeconds);193 } catch (e) {194 await audioRecorder.interrupt(true);195 await audioRecorder.cleanup();196 throw e;197 }198 this._audioRecorder = audioRecorder;199};200/**201 * Stop recording of the audio input. If no audio recording process is running then202 * the endpoint will try to get the recently recorded file.203 * If no previously recorded file is found and no active audio recording204 * processes are running then the method returns an empty string.205 *206 * @returns {string} Base64-encoded content of the recorded media file or an207 * empty string if no audio recording has been started before.208 * @throws {Error} If there was an error while getting the recorded file.209 */210commands.stopAudioRecording = async function stopAudioRecording () {211 if (!this._audioRecorder) {212 this.log.info('Audio recording has not been started. There is nothing to stop');213 return '';214 }215 let resultPath;216 try {217 resultPath = await this._audioRecorder.finish();218 if (!await fs.exists(resultPath)) {219 this.log.errorAndThrow(`${FFMPEG_BINARY} has failed ` +220 `to store the actual audio recording at '${resultPath}'`);221 }222 } catch (e) {223 await this._audioRecorder.interrupt(true);224 await this._audioRecorder.cleanup();225 this._audioRecorder = null;226 throw e;227 }228 return await encodeBase64OrUpload(resultPath);229};230export { commands };...

Full Screen

Full Screen

audio_playback.js

Source:audio_playback.js Github

copy

Full Screen

1/*2 vim:se?t ts=2 sw=2 sts=2 et cindent:3 This Source Code Form is subject to the terms of the Mozilla Public4 License, v. 2.0. If a copy of the MPL was not distributed with this5 file, You can obtain one at http://mozilla.org/MPL/2.0/.6*/7// audioPlayback Test plays an input file from a given8// <audio> and records the same to compute PESQ scores9var audioPlayback = function() {10 var test = this;11 var cleanupTimeout = 5000;12 var audio = document.createElement('audio');13 // start audio recorder14 initiateAudioRecording(test);15 if (test.failed) {16 test.finished = true;17 runNextTest();18 return;19 }20 audio.addEventListener('ended', function(evt) {21 // stop the recorder22 cleanupAudioRecording(test);23 if (!test.failed) {24 // Compute SNR and Delay between the reference25 // and the degreated files.26 getSNRAndDelay(test);27 // SNR_DELAY=5.4916,028 // We update results as 2 separate results29 var res = JSON.parse(test.http_response);30 if(res["SNR-DELAY"]) {31 // fix the test.name32 var testName = test.name;33 var snr_delay = res["SNR-DELAY"].split(",");34 test.name = testName+"_snr_in_db";35 test.results = snr_delay[0];36 updateResults(test);37 test.name = testName+"_delay_in_ms";38 test.results = snr_delay[1];39 updateResults(test);40 // restore test.name41 test.name = testName;42 }43 }44 test.finished = true;45 runNextTest();46 });47 audio.addEventListener('error', function(evt) {48 // cleanup any started processes and run the next49 // test50 cleanupAudioRecording(test);51 test.finished = true;52 runNextTest();53 });54 audio.volume = 0.9;55 audio.src = test.src;56 audio.play();...

Full Screen

Full Screen

constants.js

Source:constants.js Github

copy

Full Screen

1export const DATA_PATH = './data';2export const FFMPEG_PATH = '/usr/lib/jellyfin-ffmpeg/ffmpeg';3export const MIGRATIONS_PATH = './migrations';4export const DEFAULT_MQTT_BASE_TOPIC = 'plate-minder';5export const DEFAULT_HASS_DISCOVERY_ENABLE = false;6export const DEFAULT_HASS_DISCOVERY_PREFIX = 'homeassistant';7export const DEFAULT_IMAGE_RETAIN_DAYS = 30;8export const FILE_PLATE_RECORDER_CLEANUP_INTERVAL = 300000;9export const FILE_PLATE_RECORDER_LOG = `${DATA_PATH}/file_recorder_plate_log_do_not_modify`;10export const TOKEN_SOURCE = '{{SOURCE}}';11export const TOKEN_DATE = '{{DATE}}';12export const TOKEN_TIME = '{{TIME}}';13export const TOKEN_PLATE = '{{PLATE}}';14export const DEFAULT_REST_SERVER_PORT = 4000;15export const DEFAULT_REST_SERVER_ENABLE = true;16export const READABLE_RETRY_DELAY = 5;17export const DEFAULT_CONFIG = {18 sources: [],19 filters: [],20 openALPR: {21 url: 'http://open-alpr-http-wrapper:3000/detect'22 },23 recorders: [],24 restService: {25 enable: true,26 port: 400027 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wd = require('wd');2var assert = require('assert');3var fs = require('fs');4var path = require('path');5var os = require('os');6var _ = require('lodash');7var xcode = require('appium-xcode');8var logger = require('appium-logger').get('appium');9var log = require('appium-support').logging.getLogger('RecorderCleanup');10var { getSimulator } = require('appium-ios-simulator');11var { getDevices } = require('node-simctl');12var { SubProcess } = require('teen_process');13var { fs: fsUtils } = require('appium-support');14var { retryInterval } = require('asyncbox');15var DEFAULT_SIMULATOR_NAME = 'iPhone 11';16var DEFAULT_PLATFORM_VERSION = '13.3';17var DEFAULT_DEVICE_NAME = 'iPhone 11';18var DEFAULT_PLATFORM_NAME = 'iOS';

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Appium Xcuitest Driver automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Sign up Free
_

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful