How to use recorder.interrupt method in Appium Xcuitest Driver

Best JavaScript code snippet using appium-xcuitest-driver

driver.js

Source:driver.js Github

copy

Full Screen

...555 }556 async deleteSession () {557 await removeAllSessionWebSocketHandlers(this.server, this.sessionId);558 for (const recorder of _.compact([this._recentScreenRecorder, this._audioRecorder])) {559 await recorder.interrupt(true);560 await recorder.cleanup();561 }562 if (!_.isEmpty(this._perfRecorders)) {563 await B.all(this._perfRecorders.map((x) => x.stop(true)));564 this._perfRecorders = [];565 }566 await this.stop();567 if (this.wda && !this.opts.webDriverAgentUrl) {568 if (this.opts.clearSystemFiles) {569 let synchronizationKey = XCUITestDriver.name;570 const derivedDataPath = await this.wda.retrieveDerivedDataPath();571 if (derivedDataPath) {572 synchronizationKey = path.normalize(derivedDataPath);573 }...

Full Screen

Full Screen

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 log from '../logger';4import { encodeBase64OrUpload } from '../utils';5import { waitForCondition } from 'asyncbox';6const commands = {};7const AUDIO_RECORD_FEAT_NAME = 'audio_record';8const MAX_RECORDING_TIME_SEC = 60 * 60 * 12;9const DEFAULT_RECORDING_TIME_SEC = 60 * 3;10const PROCESS_STARTUP_TIMEOUT_MS = 5000;11const DEFAULT_SOURCE = 'avfoundation';12const DEFAULT_BITRATE = '128k';13const DEFAULT_CODEC = 'aac';14const DEFAULT_CHANNELS = 2;15const DEFAULT_RATE = 44100;16const DEFAULT_EXT = '.mp4';17const FFMPEG_BINARY = 'ffmpeg';18const ffmpegLogger = logger.getLogger(FFMPEG_BINARY);19class AudioRecorder {20 constructor (input, audioPath, opts = {}) {21 this.audioPath = audioPath;22 this.opts = opts;23 this.input = input;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 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 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 log.info(`The recording session on audio input '${this.input}' has been finished`);83 } else {84 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 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 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 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 log.info(`There is an active audio recording process`);162 if (forceRestart) {163 log.info(`Stopping it because 'forceRestart' option is set to true`);164 await this._audioRecorder.interrupt(true);165 } else {166 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, 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 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 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 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

server.js

Source:server.js Github

copy

Full Screen

1const WebSocket = require('ws')2const { randomString, rand } = require('./rand.js')3const CMD_NOTE_ON = 14const fromCmd = (cmd) => (cmd>>4) & 75const ROOT_SECRET = '0000000000000000'6const ROOT_USR = 07const ROOT_GRP = 08const PORT = process.env.PORT || 110889const wss = new WebSocket.Server({ port: PORT })10const groups = Array.from({ length: 255 }).map(() => new Set()) // 255 is offline 'room''11const identities = {} // {[secret]: { name: 'pianco', gid: 0, uid: 0 }}12const send = (gid, uid, message) => { // to specific identity13 wss.clients.forEach(client => {14 const { gid: clientGid, uid: clientUid } = identities[client.secret] || {}15 if (clientGid === gid && clientUid === uid && client.readyState === WebSocket.OPEN) {16 client.send(message)17 }18 })19}20const broadcast = (data) => { // to everyone in group21 const [gid, uid] = data22 wss.clients.forEach(client => {23 const { gid: clientGid } = identities[client.secret] || {}24 if (clientGid === gid && client.readyState === WebSocket.OPEN) {25 client.send(new Uint8Array(data))26 }27 })28}29const broadcastText = (gid, text) => {30 wss.clients.forEach(client => {31 const { gid: clientGid } = identities[client.secret] || {}32 if (clientGid === gid && client.readyState === WebSocket.OPEN) {33 client.send(text)34 }35 })36}37const echo = (data) => { // to eveyone in group except origin38 const [gid, uid] = data39 wss.clients.forEach(client => {40 const { gid: clientGid, uid: clientUid } = identities[client.secret] || {}41 if (clientGid === gid && clientUid !== uid && client.readyState === WebSocket.OPEN) {42 client.send(data)43 }44 })45}46const status = () => { // broadcast state of the world to everyone47 const data = JSON.stringify({48 groups: groups.map(uids => [...uids]),49 names: groups.map((_, group) => // [0: {0: 'draho'}, 3: {}]50 Object.values(identities)51 .filter(({ gid }) => gid === group)52 .reduce((map, {uid, name}) => ({...map, [uid]: name}), {})53 ),54 // TODO additional data in the future55 })56 wss.clients.forEach(client => {57 if (client.readyState === WebSocket.OPEN) {58 client.send(`status ${data}`)59 }60 })61}62wss.send = send63wss.broadcast = broadcast64wss.echo = echo65wss.status = status66groups[ROOT_GRP].add(ROOT_USR) // add ghost player to main room permanently67identities[ROOT_SECRET] = { name: 'pianco', gid: 0, uid: 0 }68const Autoplay = require('./autoplay.js')(wss)69const autoplayers = groups.map((_, gid) => new Autoplay(gid, ROOT_USR)) // init autoplaye for each group70const Recorder = require('./recorder.js')(wss)71const recorders = groups.map((_, gid) => new Recorder(gid)) // init recorder for each group72// return uid which is not yet in the group73const genUid = (gid) => {74 if (groups[gid].size >= 255) {75 return null76 }77 let uid78 do {79 uid = rand(255) // 0-254 - 255 is ghost80 } while (uid === ROOT_USR || groups[gid].has(uid))81 return uid82}83wss.on('connection', async function connection(ws) {84 console.log('client connected')85 ws.isAlive = true86 ws.send('connected')87 ws.on('message', function incoming(message) {88 // common vars89 let { uid, gid } = identities[ws.secret] || { uid: undefined, gid: undefined}90 const isDirectApi = ws.secret === undefined 91 if (isDirectApi) { // assume gid=0 for gopiano92 gid = ROOT_GRP93 }94 if (message instanceof Buffer) {95 if (message[0] !== 255 && message[0] !== -1) {96 echo(message) // <--- this is the most important97 recorders[gid].pass(message) // pass message to recorder98 }99 // interrupt ghost:100 if (gid === ROOT_GRP) { // gopiano also triggesr this101 const [_, __, cmd] = new Uint8Array(message)102 if (fromCmd(cmd) === CMD_NOTE_ON) { // note on103 autoplayers[ROOT_GRP].resetGhost({104 delay: 120,105 stopCurrent: true,106 pretendScared: !isDirectApi,107 })108 }109 }110 }111 if (typeof message === "string") {112 const [cmd, ...values] = message.split(' ')113 if (cmd === 'ping') {114 ws.send('pong')115 }116 if (cmd === 'reaction') {117 const [gid, uid] = values.map(Number)118 broadcastText(gid, message)119 }120 if (cmd === "regroup") {121 const [_, __, newGid] = values.map(Number)122 let [secret, name] = values.slice(3) // optional123 const { uid: oldUid, gid: oldGid } = identities[secret] ||124 { uid: undefined, gid: undefined } // after reset, or for new users - to force gen of new uid125 let newUid = oldUid // possibly unchanged126 // wipe user activity in group127 if (oldUid && oldGid >=0) {128 autoplayers[oldGid].stop(oldUid)129 recorders[oldGid].stop(oldUid)130 }131 // prepare new values:132 if (oldGid !== newGid || oldUid === undefined) { // only change uid when changing gid133 if (newGid >= 0) {134 newUid = genUid(newGid)135 } else {136 newUid = -1137 }138 if (newUid === null) {139 ws.send(`group full ${newGid} ${newUid}`)140 wss.status()141 return142 }143 }144 if (!secret) {145 if (ws.secret) {146 return console.error('cant change secret of wssecre')147 }148 secret = randomString(16)149 }150 if (!name) { // assign default random name151 name = `anon${newUid}`152 }153 // update stored values154 groups[oldGid] && groups[oldGid].delete(oldUid)155 if (newGid >= 0) {156 groups[newGid].add(newUid)157 }158 identities[secret] = { name, gid: newGid, uid: newUid }159 // update sockets160 ws.secret = secret161 // inform clients of secret162 wss.clients.forEach(ws => {163 const { uid, gid } = identities[secret]164 // send response to all ws from device165 if (ws.secret === secret && ws.readyState === WebSocket.OPEN) {166 ws.send(`regroup ${newGid} ${newUid} ${secret} ${name}`)167 console.log(`${secret}:${name} - ${uid}@${gid} => ${newUid}@${newGid}`)168 }169 })170 wss.status()171 // reset ghost player timer172 if (newGid === 0) {173 autoplayers[newGid].resetGhost({174 delay: 60,175 stopCurrent: false,176 })177 }178 }179 const recorder = recorders[gid]180 if (gid !== -1) {181 if (cmd === 'record') {182 recorder.record(uid)183 }184 if (cmd === 'stop') {185 recorder.stop(uid)186 }187 if (cmd === 'replay') {188 recorder.replay(uid)189 }190 if (cmd === 'pause') {191 recorder.pause(uid)192 }193 // debug only:194 if (cmd === 'autoplayurl') {195 const [gid, uid] = values.map(Number)196 const url = values[2]197 autoplayers[gid].requestHandler(ws)(url)198 }199 if (cmd === 'playrandomfile') {200 const [gid, uid] = values.map(Number)201 autoplayers[gid].playRandomFile(uid)202 }203 if (cmd === 'playrandomnotes') {204 const [gid, uid, count] = values.map(Number)205 autoplayers[gid].playRandomNotes(uid, count)206 }207 if (cmd === 'stopplay') {208 const [gid, uid] = values.map(Number)209 autoplayers[gid].stop(uid)210 }211 }212 // console.log(cmd, values)213 }214 })215 ws.on('close', () => {216 const { gid, uid } = identities[ws.secret] || {}217 let isLast = true218 wss.clients.forEach((client) => {219 if (client !== ws && client.readyState === WebSocket.OPEN220 && client.secret === ws.secret221 ) {222 isLast = false223 }224 })225 if (isLast && gid !== undefined && uid !== undefined) {226 if (gid >=0) {227 autoplayers[gid].stop(uid)228 recorders[gid].stop(uid)229 groups[gid].delete(uid)230 }231 if (ws.secret in identities) {232 identities[ws.secret].uid = undefined233 identities[ws.secret].gid = undefined234 }235 console.log(`${uid}@${gid} => close`)236 wss.status()237 }238 })239})240const healthInterval = setInterval(() => {241 wss.clients.forEach(ws => {242 if (ws.secret === undefined) { // ignore health of gopiano connection243 return 244 }245 if (ws.isAlive === false) {246 console.log(`ws.secret`, ws.secret)247 ws.terminate()248 return249 }250 ws.isAlive = false251 ws.ping()252 ws.once('pong', () => {253 ws.isAlive = true254 })255 })256}, 30000)257wss.on('close', () => {258 clearInterval(healthInterval)259})...

Full Screen

Full Screen

saveVideo.js

Source:saveVideo.js Github

copy

Full Screen

1import React, { Component } from 'react';2export default class SaveVideo extends Component {3 constructor() {4 super();5 // 单例6 if (!SaveVideo.instance) {7 this.state = {8 ongoing: false9 };10 SaveVideo.instance = this;11 } else {12 return SaveVideo.instance;13 }14 this.state = {15 recorder: null, 16 recorder_timeout: null,17 full_recorded: false,18 videoData: null19 }20 }21 22 initRecoder() {23 if (this.state.ongoing) {24 return25 }26 else {27 this.setState({28 ongoing: true29 })30 }31 var canvas = document.getElementById(this.props.canvas);32 33 var stream = canvas.captureStream();34 // add audio35 // let videoOrAudioElement = document.getElementById('audio');36 // let ctx = new AudioContext();37 // let dest = ctx.createMediaStreamDestination();38 // let sourceNode = ctx.createMediaElementSource(videoOrAudioElement);39 // sourceNode.connect(dest);40 // videoOrAudioElement.play();41 // sourceNode.connect(ctx.destination);42 // let audioTrack = dest.stream.getAudioTracks()[0];43 // stream.addTrack(audioTrack);44 // var recorder = new MediaRecorder(stream, { mimeType: "video/webm"});45 46 var videoData = [];47 var recorder = new MediaRecorder(stream, { mimeType: "video/webm"});48 this.setState({49 recorder: recorder50 })51 recorder.onstart = () => {52 console.log("start")53 // 播放视频54 this.props.draw();55 // 根据时间停止录制56 var recorder_timeout = setTimeout(() => {57 this.setState({58 full_recorded: true59 })60 recorder.stop(); 61 }, this.props.duration + 1000);62 this.setState({63 recorder_timeout: recorder_timeout64 });65 console.log(this.state.recorder_timeout)66 }67 recorder.ondataavailable = function(event) {68 console.log("recording");69 videoData.push(event.data); 70 }71 recorder.onstop = () => {72 // 清除timeout73 if (this.state.recorder_timeout !== null) {74 clearTimeout(this.state.recorder_timeout);75 this.setState({76 recorder_timeout: null77 })78 }79 // 如果是正常录制完毕80 if (this.state.full_recorded) {81 var url = URL.createObjectURL(new Blob(videoData, { type: "video/webm" }));82 const link = document.createElement('a');83 link.style.display = 'none';84 link.href = url;85 link.download = 'media.mp4';86 document.body.appendChild(link);87 link.click();88 link.remove();89 }90 91 this.setState({92 recorder: null,93 ongoing: false94 })95 }96 97 this.startRecoder(recorder);98 }99 startRecoder(recorder) {100 recorder.start(this.props.timeSlice);101 }102 // TODO: why stop?103 stopRecorder() {104 if (this.state.recorder !== null)105 this.state.recorder.stop();106 }107 render() {108 return (109 <div>110 <button className="saving" 111 onClick={() => this.initRecoder()}>112 save113 </button>114 <button onClick={() => this.stopRecorder()}>115 Interrupt116 </button>117 </div>118 )119 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const wdio = require('webdriverio');2const opts = {3 desiredCapabilities: {4 }5};6async function main () {7 const client = await wdio.remote(opts);8 await client.pause(10000);9 const result = await client.execute('mobile: stopRecordingScreen');10 console.log(result);11}12main();13const wdio = require('webdriverio');14const opts = {15 desiredCapabilities: {16 }17};18async function main () {19 const client = await wdio.remote(opts);20 await client.pause(10000);21 const result = await client.execute('mobile: stopRecordingScreen');22 console.log(result);23}24main();25const wdio = require('webdriverio');26const opts = {27 desiredCapabilities: {28 }29};30async function main () {31 const client = await wdio.remote(opts);32 await client.pause(10000);33 const result = await client.execute('mobile: stopRecordingScreen');34 console.log(result);35}36main();37const wdio = require('webdriverio');38const opts = {39 desiredCapabilities: {40 }41};42async function main () {

Full Screen

Using AI Code Generation

copy

Full Screen

1const wd = require('wd');2driver.init({3}).then(() => {4 return driver.sleep(5000);5}).then(() => {6 return driver.elementByName('Buttons');7}).then((el) => {8 return el.click();9}).then(() => {10 return driver.elementByName('Rounded');11}).then((el) => {12 return el.click();13}).then(() => {14 return driver.elementByName('Rounded');15}).then((el) => {16 return el.click();17}).then(() => {18 return driver.interrupt();19}).then(() => {20 return driver.elementByName('Rounded');21}).then((el) => {22 return el.click();23}).then(() => {24 return driver.elementByName('Rounded');25}).then((el) => {26 return el.click();27}).then(() => {28 return driver.quit();29}).catch((err) => {30 console.log(err);31});

Full Screen

Using AI Code Generation

copy

Full Screen

1const wdio = require('webdriverio');2const options = {3 desiredCapabilities: {4 }5};6const client = wdio.remote(options);7(async function () {8 try {9 await client.init();10 await client.pause(5000);11 await client.interrupt();12 await client.pause(5000);13 await client.end();14 } catch (e) {15 console.log(e);16 }17})();18const wdio = require('webdriverio');19const options = {20 desiredCapabilities: {21 }22};23const client = wdio.remote(options);24(async function () {25 try {26 await client.init();27 await client.pause(5000);28 await client.background(5);29 await client.interrupt();30 await client.pause(5000);31 await client.end();32 } catch (e) {33 console.log(e);34 }35})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const wd = require('wd');2driver.init({3}).then(() => {4}).then(() => {5 return driver.elementByAccessibilityId('Search');6}).then((el) => {7 return el.click();8}).then(() => {9 return driver.elementByAccessibilityId('Cancel');10}).then((el) => {11 return el.click();12}).then(() => {13 return driver.interrupt();14}).then(() => {15 return driver.quit();16});17const wd = require('wd');18driver.init({19}).then(() => {20}).then(() => {21 return driver.elementByAccessibilityId('Search');22}).then((el) => {23 return el.click();24}).then(() => {25 return driver.elementByAccessibilityId('Cancel');26}).then((el) => {27 return el.click();28}).then(() => {29 return driver.interrupt('com.apple.mobilesafari');30}).then(() => {31 return driver.quit();32});332017-05-25 09:28:05:792 - [debug] [BaseDriver] Event 'newSessionRequested' logged at 1495671285789 (09:28:05 GMT+

Full Screen

Using AI Code Generation

copy

Full Screen

1let recorder = await driver.startRecordingScreen();2await driver.pause(10000);3await recorder.interrupt();4await driver.pause(10000);5await recorder.stop();6let recorder = await driver.startRecordingScreen();7await driver.pause(10000);8await recorder.interrupt();9await driver.pause(10000);10await recorder.stop();11let recorder = await driver.startRecordingScreen();12await driver.pause(10000);13await recorder.interrupt();14await driver.pause(10000);15await recorder.stop();16let recorder = await driver.startRecordingScreen();17await driver.pause(10000);18await recorder.interrupt();19await driver.pause(10000);20await recorder.stop();21let recorder = await driver.startRecordingScreen();22await driver.pause(10000);23await recorder.interrupt();24await driver.pause(10000);25await recorder.stop();26let recorder = await driver.startRecordingScreen();27await driver.pause(10000);28await recorder.interrupt();29await driver.pause(10000);30await recorder.stop();31let recorder = await driver.startRecordingScreen();32await driver.pause(10000);33await recorder.interrupt();34await driver.pause(10000);35await recorder.stop();36let recorder = await driver.startRecordingScreen();37await driver.pause(10000);38await recorder.interrupt();39await driver.pause(10000);40await recorder.stop();41let recorder = await driver.startRecordingScreen();42await driver.pause(10000);43await recorder.interrupt();44await driver.pause(10000);45await recorder.stop();

Full Screen

Using AI Code Generation

copy

Full Screen

1const wd = require('wd');2const path = require('path');3const fs = require('fs');4const _ = require('lodash');5const { exec } = require('child_process');6const { execSync } = require('child_process');7const { sleep } = require('asyncbox');8const { retryInterval } = require('asyncbox');9const { retry } = require('asyncbox');10const { waitForCondition } = require('asyncbox');11const { waitForConditionInLoop } = require('asyncbox');12const { waitForConditionInLoopWithRetries } = require('asyncbox');13const { retrying } = require('asyncbox');14const { retryingInterval } = require('asyncbox');15const { retryingWithBackOff } = require('asyncbox');16const { retryingWithBackOffInterval } = require('asyncbox');17const { retryingWithBackOffIntervalAndTimeout } = require('asyncbox');18const { retryingWithBackOffIntervalAndTimeoutAndJitter } = require('asyncbox');19const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptions } = require('asyncbox');20const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndCondition } = require('asyncbox');21const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetries } = require('asyncbox');22const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeout } = require('asyncbox');23const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeoutAndInterval } = require('asyncbox');24const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeoutAndIntervalAndIntervalModulus } = require('asyncbox');25const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeoutAndIntervalAndIntervalModulusAndIntervalMultiplier } = require('asyncbox');26const { retryingWithBackOffIntervalAndTimeoutAndJitterAndExceptionsAndConditionAndRetriesAndTimeoutAndIntervalAndIntervalModulusAndIntervalMultiplierAndBackOffFactor } = require('asyncbox');27const { retryingWithBackOffInterval

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