iOS 制作来电铃声
上图是酷狗音乐App iOS制作铃声的界面,如果你的产品给你整这个需求,你会怎么做呢?我操起手机反复体验酷狗的这个功能后,总结出要实现这个功能,只要4个步骤:
一、下载音频资源
使用 URLSessionDownloadTask 下载音频
//传入音频资源URL和保存的路径
downloader.downloadFile(from: audioUrl, saveToPath: savePath)
// 下载进度
downloader.progressHandler = { progress in
YLLog("下载进度:\(progress)")
}
//下载成功
downloader.completionHandler = {[weak self] destinationURL, error in}
二、绘制音轨图
使用DSWaveformImage 来绘制音轨图
https://github.com/dmrschmidt/DSWaveformImage
//audioURL 下载保存的路径
self.audioWaveformView.waveformAudioURL = audioURL
lazy var audioWaveformView: WaveformImageView = {
let tempImageV = WaveformImageView(frame: .zero)
tempImageV.waveformStyle = .striped(.init(color: UIColor(hexString: "#FFFFFF"), width: scaleWidth(2), spacing: scaleWidth(2)))
audioWavebgV.addSubview(tempImageV)
return tempImageV
}()
三、音频裁剪、编辑
音频裁剪
传入本地音频路径和开始结束时间,代码不多就直接贴出来
也可以支持一下😁 AudioClipping 音频裁剪
func trimAudio(audioURL: URL, startTime: Double, endTime: Double, completion: @escaping (URL?, Error?) -> Void) {
let asset = AVAsset(url: audioURL)
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else {
completion(nil, NSError(domain: "com.yourDomain", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to create AVAssetExportSession object."]))
return
}
let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("trimmedAudio.m4a")
if FileManager.default.fileExists(atPath: outputURL.path) {
do {
try FileManager.default.removeItem(at: outputURL)
} catch {
completion(nil, error)
return
}
}
let startCMTime = CMTimeMakeWithSeconds(startTime, preferredTimescale: 1000000)
let endCMTime = CMTimeMakeWithSeconds(endTime, preferredTimescale: 1000000)
let timeRange = CMTimeRangeFromTimeToTime(start: startCMTime, end: endCMTime)
exportSession.outputFileType = AVFileType.m4a
exportSession.outputURL = outputURL
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
switch exportSession.status {
case .completed:
completion(outputURL, nil)
case .failed, .cancelled:
completion(nil, exportSession.error)
default:
break
}
}
}
编辑音频
主要是UI上的东西,麻烦的是计算滑块位置和控制最大最小移动距离
核心代码:
//给滑块添加长按手势
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(dragWithLongGestureGesture(_:)))
longGesture.minimumPressDuration = 0
tapView.addGestureRecognizer(longGesture)
//观察手势改变,更新滑块位置
@objc private func dragWithLongGestureGesture(_ gesture: UILongPressGestureRecognizer) {
switch gesture.state {
case .began:
case .changed:
//更新滑块位置
case .ended:
}
}
四、导出到库乐队设置铃声
如何将裁剪的音频生成库乐队识别的 .band 文件呢?
据我所知,好像苹果没有提供Api 直接生成.band 文件,这样的话我们就只有走曲线救国的道路了。
库乐队band文件展开后就是下图这个样子,试想一下,如果我们将这个ringtone.aiff的音频文件替换成我们自己的音频,会不会成功呢?
光说不练假把式,试试就试试···
- 准备一个没有音频文件的.band文件,导入项目中,就是只将音频文件删除,其它都保留,复制一份存到沙盒中
- 将我们上一步骤截取的音频文件转换成.aiff格式
- 再将.aiff文件保存到沙盒中的.band文件下的Media目录下
- 最后导出到库乐队设置铃声
func makeBandFolder(trimurl:URL){
//1.先拷贝一个bandFolder
let copyAtPath = BandConfigure.share.bandfoldersPath
let copyToPath = BandConfigure.share.bandfolderDirectoryURL!.appendingPathComponent("素颜.band").path
let fileManager = FileManager.default
try? fileManager.copyItem(atPath: copyAtPath, toPath: copyToPath)
//2.然后要把你自己的音频转码为aiff
let aiffFilePath = copyToPath + "/Media/ringtone.aiff"
let extAudio = ExtAudioConverter()
extAudio.inputFile = trimurl.path
extAudio.outputFile = aiffFilePath
extAudio.outputFileType = kAudioFileAIFFType
let isconvert:Bool = extAudio.convert()
if fileManager.fileExists(atPath: copyToPath),isconvert{
let bandResource = URL(fileURLWithPath: copyToPath)
DispatchQueue.main.async {
//3.弹出系统分享 选择库乐队导出
let activityViewController = UIActivityViewController(activityItems: [bandResource], applicationActivities: nil)
activityViewController.excludedActivityTypes = [.addToReadingList, .assignToContact,.postToWeibo,.mail,.airDrop,.message]
self.present(activityViewController, animated: true, completion: nil)
}
}
}
如果觉得文章对你有用,那就点个赞支持一下吧!如果有任何疑问或写得不好的地方欢迎在评论区留言 🙏