์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- UIRefreshController
- RxSwift
- ์ฑ๋ง๋ค๊ธฐ
- Cloud Firestore
- CRUD
- SWiFT
- ํ๋ก๊ทธ๋๋จธ์ค
- map
- ExpressJS
- Encodable
- Figma
- DispatchQueue
- AVAudioPlayer
- Decodable
- Reduce
- Filter
- nodejs
- Firestore
- ์ฑ๋์์ธ
- components
- String.Index
- ์๊ณ ๋ฆฌ์ฆ
- Mac
- ios
- Codable
- MongoDB
- ์ง๋ฒ๋ณํ
- Firestore CRUD
- Core Data
- mongoose
- Today
- Total
Focus On Develop ๐ค๐ค
[Swift] Audio Recording ๋ณธ๋ฌธ
์ค๋์ Swift์์ AVAudioRecorder ๋ฅผ ํ์ฉํ ๋ น์๊ธฐ๋ฅ์ ๋ํด ๊ณต๋ถํด๋ณด๋ ค๊ณ ํด์!
๋จผ์ ๋ น์๋ ํ์ผ์ ๋ก์ปฌ ๊ฒฝ๋ก์ ์ ์ฅํ๊ณ , ๋ถ๋ฌ์ค๋ ๊ณผ์ ์ด ์์ผ๋ FileManager๋ฅผ ๋จผ์ ๋ณด์๊ธธ ์ถ์ฒ๋๋ ค์ ๐
๋จผ์ Swift์์ ๋ฏธ๋์ด(์์, ์ค๋์ค ๋ฑ)์ ๋ค๋ฃฐ๋๋ AVFoundation๋ฅผ ํ์ฉํด์ ๋๋ถ๋ถ ๊ฐ๋ฅํฉ๋๋ค.
์ค๋์ค์ ๊ด๋ จ๋ ์ฌํญ์ AVAudioRecord, AVAudioPlayer, AVAudioSession, AVAudioEngine ๋ฑ๋ฑ ๋ง์ ํด๋์ค๋ก ์ง์์ ํด์ค์. AVFoundation์ importํ๊ณ ์์ํด์ฃผ์ธ์~!
๋จผ์ ๋ น์์ ์ํด์ ์ค๋์ค ์ธ์ ์ด ํ์ํฉ๋๋ค. ๐ AVAudioSession
์ค๋์ค ์ธ์ ์ ํตํด ๋ น์/์ฌ์ ๋ฑ์ ๋ํ ๊ถํ, ์ด๋ค ์ข ๋ฅ์ ๋ น์์ธ์ง, ์ด๋ค ๋ง์ดํฌ๋ฅผ ์ฌ์ฉํ ๊ฑด์ง ๋ฑ์ ์ค์ ํ ์ ์์ด์.
๋จผ์ ๊ถํ์ ์์ฒญํ๊ธฐ ์ํด, info.plist์ ์ค๋์ค ๊ด๋ จ ํญ๋ชฉ์ ์ถ๊ฐํด์ค๋๋ค. (Privacy - Microphone Usage Description)
recordingSession = AVAudioSession.sharedInstance()
// ๊ถํ
AVAudioSession.sharedInstance().requestRecordPermission { (accepted) in
if accepted {
print("permission granted")
}
}
AVAudioSession.sharedInstance() ๋ผ๊ณ ์ค๋์ค ์ธ์ ์ ๊ฐ์ ธ ์ค๊ณ , requestRecordPermission ๋ฉ์๋๋ฅผ ํตํด ์ค๋์ค ์ ๊ทผ ๊ถํ์ ์์ฒญํ๊ณ , ๊ถํ์ ์๋ฝํ๋์ง ์๋์ง๋ฅผ ๋ฐ์์ฌ ์ ์์ด์.
์ด๋ฐ ํ์ ! ๋ง์ด ๋ณด์ จ์ฃ ~? requestRecordPermission ๋ฉ์๋๋ก plist์ ์ ๋ณด๋ฅผ ์กฐํฉํด์ ์ด ํ์ ์ ๋์์ค๊ฑฐ์์!
๊ถํ์ ์ป์์ผ๋ ๋ น์์ ํด๋ณผ๊ฑฐ์์.
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord)
try recordingSession.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)
let filename = getDirectory().appendingPathComponent("\(tag).m4a")
audioRecoder = try AVAudioRecorder(url: filename, settings: settinigs)
audioRecoder.record()
} catch {
print(" fail to record ")
}
์๊น ์์์ ์ค๋์ค ์ธ์ ์ ์ด๋ค ์ข ๋ฅ์ ๋ น์์ธ์ง, ์ด๋ค ๋ง์ดํฌ์ธ์ง๋ ์ค์ ํ ์ ์๋ค๊ณ ํ์ฃ ?
์ด๋ ๊ฒ AVAudioSession.Category์์ ์ด๋ค ์ข ๋ฅ๋ฅผ ๋ น์ํ ๊ฑด์ง(Ambient, play, playAndRecord, playback ๋ฑ) ๋ฅผ ์ค์ ํ๊ณ , setCategory() ๋ฉ์๋๋ก ์ค์ ์ ์ ์ฉ์์ผ์ค์. ์ฐ๋ฆฌ๋ ๋ น์ํ๊ณ ์ฌ์ํ ๊ฑฐ๋ผ์ playAndRecord๋ฅผ ์ง์ ํด์คฌ์ด์.
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord)
๋ค์์ ์ด๋ค ๋ง์ดํฌ๋ฅผ ์ฌ์ฉํ ๊ฑด์ง๋ฅผ ์ ํด์ค๊ฑฐ์์. AVAudioSession.PortOverride.speaker ์ด๋ ๊ฒ ์คํผ์ปค๋ฅผ ์ฌ์ฉํ๊ฒ ๋ค๊ณ overrideOutputAudioPort() ๋ฉ์๋๋ฅผ ํตํด ์ค์ ํด์ค๋๋ค.
try recordingSession.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)
๊ทธ๋ฆฌ๊ณ ๋ น์ํ์ผ์ด ์ ์ฅ๋ ์์น์ ํ์ผ๋ช ์ ์ ํด์ค์๋ค.
getDirectory()๋ ๊ฐ๋จํ FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] ๋ก์ปฌ ๊ฒฝ๋ก๋ฅผ ๊ฐ์ ธ์ค๋๋ก ํ์ด์. FileManager๋ ์ฌ๊ธฐ์ ๋ฐ๋ก ์์ฑํ์ผ๋ ํจ์คํฉ๋๋ค!
let filename = getDirectory().appendingPathComponent("\(tag).m4a")
๋ง์ง๋ง์ผ๋ก ๋ น์ ํ์ง์ ๋ช ์์ ์ผ๋ก ์ ํด์ค ์ ์์ด์.
๋ด๋ถ ํฌ๋งท์ ์ด๋ป๊ฒ ํ ๊ฑด์ง, ์ฃผํ์(?) ํค๋ฅด์ธ ๋ ์ด๋ป๊ฒ ํ ๊ฑด์ง, ํ์ง์ ์ด๋ป๊ฒ ํ ๊ฑด์ง ๋ฑ์ ์ ํด์ค ์ ์์ด์.
let settinigs = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
์ด์ ๋ ์์์ ์ค์ ํ๋ ์ ๋ณด๋ก ๋ น์๊ธฐ๋ง ์ธํ ํด์ฃผ๋ฉด ๋ฉ๋๋ค.
audioRecoder = try AVAudioRecorder(url: filename, settings: settinigs)
audioRecoder.record()
record() ๋ฉ์๋๋ฅผ ํตํด ์ค์ ๋ น์์ ์์ํ ์ ์์ด์. ๋ฐ๋๋ก ๋ น์์ ์ค์งํ๋๊ฑด stop() ๋ฉ์๋๋๋๋ค.
๋ น์์ ํ์ผ๋ ์ฌ์๋ ํด๋ณผ๊น์? ์ฌ์์ ์ ๋ง๋ก ๊ฐ๋จํด์.
let filePath = getDirectory().appendingPathComponent("\(tag).m4a")
do {
audioPlayer = try AVAudioPlayer(contentsOf: filePath)
audioPlayer.play()
} catch {
print("faild to play file")
}
์๊น ์ ์ฅํ๋ ๊ฒฝ๋ก์์ ํ์ผ์ ๊ฐ์ ธ์์, AVAudioPlayer์ play() ๋ฉ์๋๋ฅผ ํตํด ์ฌ์ํ ์ ์์ต๋๋ค.
์์ฃผ ๊ฐ๋จํ ์์ ๋ก ์ค๋์ค ๋ น์/์ฌ์์ ํ๋ฒ ์์๋ณด์๋๋ฐ์!
์๋์ฒ๋ผ 4๊ฐ์ง ๋ น์์ด ๊ฐ๋ฅํ๊ณ , ๊พน ๋๋ฅด๋ฉด ๋ น์์์, ์๋ฃ๋๋ฉด play๊ฐ ๊ฐ๋ฅํ๋๋ก ๋ง๋ ์ค์ต ์ฑ๋ ๋ง๋ค์ด ๋ณด์์ด์.
์ ์ฒด ์์ค์ ๋ํ ์์ ๋ ์ฌ๊ธฐ์ ๋ค์ด๋ก๋ ๊ฐ๋ฅํฉ๋๋ค. ๐ github.com/Nurys-KT/RecodeApp
์์ฑ ๋ณ์กฐ๋, ํจ๊ณผ๋ฅผ ๋ํ๊ณ ์ถ์ ๋ถ์ AVAudioEngine, AVAudioUnitEffect์ ์ถ๊ฐ๋ก ๊ณต๋ถํด๋ณด์๋ฉด ๋ฉ๋๋ค!
๊ทธ๋ผ ์ค๋๋ ๋๊ตฐ๊ฐ์๊ฒ ๋์์ด ๋์๊ธธ ๋ฐ๋์ ๐
'iOS [Swift] > ๊ธฐ์ด๋ฅผ ํํํ!' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] Singleton Pattern (์ฑ๊ธํค ํจํด) (0) | 2021.03.16 |
---|---|
[Swift] FileManager (0) | 2021.03.02 |
[Swift] CaseIterable (0) | 2021.02.27 |
[Swift] typealias (0) | 2021.02.26 |
[Swift] Codable (0) | 2021.02.26 |