I am using AVAudioPlayer to play an audio in SwiftUI which I am fetching from Firebase. It is playing successfully. I had made a slider to show how much sound is played and how much is remaining. This is also working fine but the problem I am facing is when I use the slider to move forward or backward it should start the audio from that part.
This is what I had done so far:
struct AudioMessageView: View {
@ObservedObject var vm = ViewModel()
var body: some View {
HStack {
Button {
vm.startPlaying(url: URL(string: "https://firebasestorage.googleapis.com:443/v0/b/unified-45b5c.appspot.com/o/AudioMessage%2F8%2B5%2F5_Audio_15-09-202211:18:05.m4a?alt=media&token=acdda32e-ea2b-4ac0-acf5-7a8bd26918e2"))
} label: {
HStack(spacing: 20) {
Image(systemName: "pause.fill")
.foregroundColor(sender .black)
.padding([.top, .bottom])
Text("\(vm.convertToTimeInterval())")
.foregroundColor(.white)
}
}
ZStack(alignment: Alignment(horizontal: .leading, vertical: .center)) {
Capsule()
.fill(Color.black.opacity(0.6))
.frame(width: 250, height: 6)
ZStack(alignment: Alignment(horizontal: .trailing, vertical: .center)) {
Capsule()
.fill(.blue)
.frame(width: vm.value, height: 6)
Circle()
.fill(.blue)
.frame(width: 20, height: 20)
.clipShape(Circle())
}
}.gesture(DragGesture().onChanged({ (value) in
if value.location.x <= 250 && value.location.x >= 0 {
self.vm.value = value.location.x
}
}))
}
}
}
And in my ViewModel :
class ViewModel: NSObject, ObservableObject , AVAudioPlayerDelegate {
@Published var value : CGFloat = 0
@Published var plusValue = 0
@Published var remainingTime = 0
@Published var isStartPlay : Bool = false
var audioPlayer : AVAudioPlayer!
func startPlaying(url : URL) {
do {
let session = AVAudioSession.sharedInstance()
try session.setCategory(AVAudioSession.Category.playback)
let soundData = try Data(contentsOf: url)
audioPlayer = try AVAudioPlayer(data: soundData)
audioPlayer.prepareToPlay()
audioPlayer.play()
let totalDuration = Int(audioPlayer.duration)
self.remainingTime = totalDuration
let plus = 250 / totalDuration
print("time remain: \(remainingTime)")
var timer = Timer()
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
if self.remainingTime > 0 {
self.remainingTime -= 1
self.value += CGFloat(plus)
} else {
audioPlayer.stop()
self.isStartPlay = false
timer.invalidate()
}
}
} catch {
print("Playing Failed")
print(error.localizedDescription)
}
}
}
I want this to work like the WhatsApp audio. Is this will be achieved using this code or I had to change it? I just want this to be like WhatsApp.
