## 從 iOS 模擬器和真機中捕獲語音
### 客戶端側 API
從 Appium 1.18.0 開始,就可以在 iOS 上錄制語音并在客戶端側將語音保存到文件中去。蘋果并未提供
任何可以直接從模擬器或者真機中獲取語音流的接口。但是我們可以將語音流重定向到宿主機器上,這樣就可以捕獲語音流了。
#### mobile: startAudioRecording
根據給定的語音壓縮參數,開始在指定的主機上錄制語音。
#### 支持的參數
* _audioInput_: 用來捕獲語音的輸入設備名字,比如 `:1`。在終端使用 `ffmpeg -f avfoundation -list_devices true -i ""`命令可以列出所有的捕獲設備。該參數為必填參數。
* _audioCodec_: 語音解碼器的名字. 默認是`aac`。
* _audioBitrate_: 語音流的碼率,默認是`128k`。
* _audioChannels_: 生成的語音流的聲道數量。設置為 `1` 就會創建單聲道的語音流。默認是 `2`。
* _audioRate_: 采樣率。默認 `44100`。
* _timeLimit_: 最長錄音時間,單位秒。默認是 `180`,最長為 `43200` (12 hours)。
* _forceRestart_: 當調用 startRecordingAudio 時,是否要強制重啟語音錄制過程,或者忽略該調用,直到當前語音錄制完成。默認是 `false`,即不強制重啟。
#### mobile: stopAudioRecording
停止語音錄制流程(之前通過調用startAudioRecording啟動)。stopAudioRecording 方法的返回結果是一個base64位編碼的 .mp4 文件,該文件錄制了從 `startAudioRecording` 調用開始的語音。如果之前`startAudioRecording`沒有調用過,會產生一個空字符串。
#### 示例
```java
// Java
driver.executeScript("mobile: startAudioRecording", ImmutableMap.of("audioInput", ":1"));
Thread.sleep(10000);
byte[] mp4Data = Base64.getMimeDecoder()
.decode((String) driver.executeScript("mobile: stopAudioRecording"));
try (FileOutputStream fos = new FileOutputStream("out.mp4")) {
fos.write(mp4Data);
}
```
```ruby
# Ruby
@driver.execute_script 'mobile: startAudioRecording', audioInput: ':0'
sleep 10
base64_str = @driver.execute_script 'mobile: stopAudioRecording'
File.write 'out.mp4', Base64.decode64(base64_str)
```
```python
# Python
driver.execute_script('mobile: startAudioRecording', {'audioInput': ':1'})
time.sleep(10)
base64_str = driver.execute_script('mobile: stopAudioRecording')
with open('out.mp4', 'wb') as f:
f.write(base64.b64decode(base64_str))
```
### 服務端所需配置
Appium 的版本需要大于等于 1.18.0。
宿主機必須安裝了 [FFMPEG](https://www.ffmpeg.org/download.html),并且該命令已經配置到系統路徑中去了。在 macOS 上,可以通過 [Brew](https://brew.sh/) 命令安裝:`brew install ffmpeg`。
macOS 從 10.15 開始,macOS需要可以錄制語音的應用必須顯示激活。激活路徑:System Preferences->Security & Privacy->Privacy->Microphone tab。
確保 FFMPEG 或者 Appium 進程 (比如 Terminal) 在激活列表中。
該功能有潛在的安全風險,所以必須在服務端側顯示允許。該功能的名字是 `audio_record`。更多細節參見[Security](/writing-running-appium/security.md) 。
### 模擬器設置
在 iOS 模擬器上進行語音錄制,需要進行如下配置:
* 安裝 [Soundflower](https://github.com/mattingalls/Soundflower/releases)
* 將模擬器的語音輸出重定向到 Soundflower。 在 模擬器的主菜單選擇 I/O->Audio Output->Soundflower (2ch)。
* 在終端運行 `ffmpeg -f avfoundation -list_devices true -i ""` 得到 `Soundflower (2ch)` 的標識名字。這個標識使用 `:` 做為前綴。把這個標識作為 `audioInput` 的參數來調用 `mobile: startAudioRecording`。
* 測試你的配置是否生效。在模擬器里播放任意一個錄音,然后在終端執行該命令:`ffmpeg -t 5 -f avfoundation -i ":1" -c:a aac -b:a 128k -ac 2 -ar 44100 -y ~/Desktop/out.mp4`(注意-i的參數值需要設置為上一步得到的值)。5秒后,在你的桌面就會有一個 `out.mp4` 文件,該文件錄制了剛剛的語音。
### 真機設置
在真機上進行語音錄制,需要進行如下配置:
* 將你的真機設備和mac電腦鏈接。
* 運行 `open -a /System/Applications/Utilities/Audio\ MIDI\ Setup.app` ,啟動應用。
* 在列表中找到你的手機,然后點擊 `Enable`按鈕激活。
* 在終端運行 `ffmpeg -f avfoundation -list_devices true -i ""` ,在`AVFoundation audio devices`列表中找到手機的標識名字。這個標識使用 `:` 做為前綴。把這個標識作為 `audioInput` 的參數來調用 `mobile: startAudioRecording`。
* 測試你的配置是否生效。在手機里播放任意一個錄音,然后在終端執行該命令:`ffmpeg -t 5 -f avfoundation -i ":1" -c:a aac -b:a 128k -ac 2 -ar 44100 -y ~/Desktop/out.mp4`(注意-i的參數值需要設置為上一步得到的值)。5秒后,在你的桌面就會有一個 `out.mp4` 文件,該文件錄制了剛剛的語音。
蘋果不允許電話錄音重定向,所以你只能錄制應用或者系統的聲音。
### 拓展閱讀
* https://github.com/appium/appium-xcuitest-driver/pull/1207
* https://www.macobserver.com/tips/quick-tip/iphone-audio-input-mac/
* http://www.lorisware.com/blog/2012/04/28/recording-iphone-emulator-video-with-sound/
- 關于TesterHome和MTSC
- 關于Appium
- 簡介
- Appium 客戶端
- 入門指南
- 已支持的平臺
- API 文檔
- Appium驅動
- XCUITest (iOS)
- XCUITest Real Devices (iOS)
- UIAutomation (iOS)
- UIAutomation Safari Launcher (iOS)
- UIAutomator (Android)
- UIAutomator2 (Android)
- Espresso (Android)
- Windows
- Mac
- Appium命令
- Status
- Execute Mobile Command
- Session
- Create
- End
- Get Session Capabilities
- Go Back
- Screenshot
- Source
- Timeouts
- Timeouts
- Implicit Wait
- Async Script
- Orientation
- Get Orientation
- Set Orientation
- Geolocation
- Get Geolocation
- Set Geolocation
- Logs
- Get Log Types
- Get Logs
- Events
- Log event
- Get events
- Settings
- Update Settings
- Get Device Settings
- Settings
- Update Settings
- Get Device Settings
- Execute Driver Script
- Device
- Activity
- Start Activity
- Current Activity
- Current Package
- App
- Install App
- Is App Installed
- Launch App
- Background App
- Close App
- Reset App
- Remove App
- Activate App
- Terminate App
- Get App State
- Get App Strings
- End Test Coverage
- Clipboard
- Get Clipboard
- Set Clipboard
- Emulator
- Power AC
- Power Capacity
- Files
- Push File
- Pull File
- Pull Folder
- Interactions
- Shake
- Lock
- Unlock
- Is Locked
- Rotate
- Keys
- Press keycode
- Long press keycode
- Hide Keyboard
- Is Keyboard Shown
- Network
- Toggle Airplane Mode
- Toggle Data
- Toggle WiFi
- Toggle Location Services
- Send SMS
- GSM Call
- GSM Signal
- GSM Voice
- Network Speed
- Performance Data
- Get Performance Data
- Performance Data Types
- Screen Recording
- Start Screen Recording
- Stop Screen Recording
- Simulator
- Perform Touch ID
- Toggle Touch ID Enrollment
- System
- Open Notifications
- System Bars
- System Time
- Display density
- Authentication
- Finger Print
- Element
- Find Element
- Find Elements
- Actions
- Click
- Send Keys
- Clear
- Attributes
- Text
- Name
- Attribute
- Selected
- Enabled
- Displayed
- Location
- Size
- Rect
- CSS Property
- Location in View
- Other
- Submit
- Active Element
- Equals Element
- Context
- Get Context
- Get All Contexts
- Set Context
- Interactions
- Mouse
- Move To
- Click
- Double Click
- Button Down
- Button Up
- Touch
- Single Tap
- Double Tap
- Move
- Touch Down
- Touch Up
- Long Press
- Scroll
- Flick
- Multi Touch Perform
- Touch Perform
- W3C Actions
- Web
- Window
- Set Window
- Close Window
- Get Handle
- Get Handles
- Get Title
- Get Window Size
- Set Window Size
- Get Window Position
- Set Window Position
- Maximize Window
- Navigation
- Go to URL
- Get URL
- Back
- Forward
- Refresh
- Storage
- Get All Cookies
- Set Cookie
- Delete Cookie
- Delete All Cookies
- Frame
- Switch to Frame
- Switch to Parent Frame
- Execute Async
- Execute
- 編寫 & 運行Appium腳本
- Running Tests
- Desired Capabilities
- The --default-capabilities flag
- Finding Elements
- Touch Actions
- CLI Arguments
- Server Security
- Web/Web Views
- Mobile Web Testing
- Automating Hybrid Apps
- Using ios-webkit-debug-proxy
- Using Chromedriver
- Image Comparison
- iOS
- Low-Level Insights on iOS Input Events
- XCUITest Mobile Gestures
- XCUITest Mobile App Management
- iOS Pasteboard Guide
- iOS Predicate Guide
- iOS Touch ID Guide
- iOS Install Certificate
- tvOS support
- Pushing/Pulling files
- Audio Capture
- Android
- Low-Level Insights on Android Input Events
- UiSelector Guide
- Espresso Datamatcher Guide
- Android Code Coverage Guide
- Activities Startup Troubleshooting Guide
- How To Execute Shell Commands On The Remote Device
- Android Device Screen Streaming
- How To Emulate IME Actions Generation
- How To Test Android App Bundle
- Other
- Reset Strategies
- Network Connection Guide
- Using Unicode with Appium
- Troubleshooting
- Tutorial
- Swipe Tutorial
- Screen
- Element
- Partial screen
- Simple
- Multiple scroll views
- Add scroll layout
- Tricks and Tips
- Screen
- Element
- Element search
- Fast
- Slow
- Guide
- 進階概念
- 定位圖像中的元素
- 使用定位元素的插件
- 遷移到 XCUITest
- 在 Appium 中使用 Selenium Grid
- Appium Logs Filtering
- 跨域 iframes
- 使用自定義 WDA 服務器
- 使用不同版本的 Xcode 運行
- The Event Timings API
- 并行測試的設置
- The Settings API
- Memory Collection
- 向Appium項目做貢獻
- 從源代碼運行 Appium
- 開發者概述
- 標準開發命令
- Appium 風格指南
- 如何編寫文檔
- Appium 包結構
- 鳴謝