我想用uts做一个音频播放的,然后调用的方法的时候,报了这个错,我重新打过包也一样
17:04:55.349 [Vue warn]: Error in onLoad hook: "Error: undefined class: UTSSDKModulesUtsAudioPlayerIndexSwift"[ERROR] : [Vue warn]: Error in onLoad hook: "Error: undefined class: UTSSDKModulesUtsAudioPlayerIndexSwift"(found at pages/chatroom/info.vue:1) __ERROR
17:04:55.365 Error: undefined class: UTSSDKModulesUtsAudioPlayerIndexSwift __ERROR
还有一个问题就是:uts的switch break 问题,
uts的语法文档写了是可以[break;],https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html#switch-%E8%AF%AD%E5%8F%A5,但是在编译的时候报错了
17:13:22.725 126 | //this.playAudio()
17:13:22.725 127 | [break;]
17:13:22.741 : ^^^^^
17:13:22.741 127 |
17:13:22.741 `----
17:13:22.756 Caused by:
17:13:22.756 Syntax Error
// index.uts代码
// 引用 iOS 原生平台 api
import { URL, NSKeyValueObservingOptions, NSKeyValueChangeKey, NSNotification, NotificationCenter } from 'Foundation'
import { CMTimeRange, CMTime } from 'CoreMedia'
import { UIDevice } from 'UIKit'
import { AVPlayer, AVPlayerItem } from 'AVFoundation'
import { DispatchQueue } from 'Dispatch'
class NetAudioPlayerTool extends NSObject {
// player?: AVPlayer // 声明一个字符串变量
// playerItem?: AVPlayerItem
// //正在播放回调
// //currentTime 播放时间
// //currentProgress 播放进度
// typealias OnPlayingBlock = (@argumentLabel("_") currentTime:Float64, @argumentLabel("_") currentProgress:Float) -> ();
// //准备播放回调
// //totalDuration 音频总时长
// typealias PrepareToPlayBlock = (@argumentLabel("_") totalDuration:Float) -> ();
// //正在缓冲回调
// //bufferDuration 已缓冲的时长
// typealias OnBufferingBlock = (@argumentLabel("_") bufferDuration:Float) -> ();
// //播放完成回调
// //flag YES播放完成, NO播放失败
// typealias CompletePlayingBlock = (@argumentLabel("_") flag:Bool) -> ();
// //缓存自动暂停回调, 用于更改播放按钮的样式
// //bufferDuration isPlaying 是否正在播放, 如果没有播放表示正在缓冲
// typealias IsPlayingBlock = (@argumentLabel("_") isPlaying:Float) -> ();
// playingBlock:OnPlayingBlock?
// prepareToPlayBlock:PrepareToPlayBlock?
// bufferingBlock:OnBufferingBlock?
// completePlayBlock:CompletePlayingBlock?
// isPlayingBlock:IsPlayingBlock?
playerItem?:AVPlayerItem
//播放器
player:AVPlayer = AVPlayer()
//播放路径
audioPath:String = ""
//音量大小
volume:Float = 1.0
// 只有当播放器状态为`ReadyToPlay`,才可以执行拖拽操作,否则crash.
canDraggingFlag:Bool = false
//之前播放的进度
timeOffset:Float64 = 0
//播放时间
currentTime:Float64 = 0
//音频总时长
totalDuration:Float64 = 0
override init() {
super.init()
this.addObserverForPlayer()
}
//MARK:创建播放器
createPlayer(uri: string) {
let url = new URL(_string = uri)
this.playerItem = new AVPlayerItem(URL = url)
this.player = new AVPlayer(item = this.playerItem)
this.player.rate = 1.0
this.player.volume = this.volume
//与播放缓存相关的观测属性
this.addObserverForPlayItem()
}
//MARK:开始播放
playAudio() {
this.player.play()
}
//MARK:暂停播放
pauseAudio() {
this.player.pause()
}
//MARK:停止播放
stopAudio() {
this.destroyPlayer()
}
//MARK:改变播放进度
changeAudio(currentTime:Float64) {
if (currentTime>0) {
let time:CMTime = CMTimeMakeWithSeconds(currentTime, preferredTimescale = 1 * Int32(NSEC_PER_SEC))
this.player.seek(to = time, toleranceBefore = CMTime.zero, toleranceAfter = CMTime.zero)
this.player.play()
}
}
//MARK:Notification
//播放完毕
addObserverForPlayer() {
const method = Selector("audioPlayCompletion")
NotificationCenter.default.addObserver(this, selector = method, name = NSNotification.Name.AVPlayerItemDidPlayToEndTime, object = null)
}
addObserverForPlayItem() {
this.player.currentItem?.addObserver(this, forKeyPath = "status", options = NSKeyValueObservingOptions.new, context = null);
this.player.currentItem?.addObserver(this, forKeyPath = "loadedTimeRanges", options = NSKeyValueObservingOptions.new, context = null);
this.player.currentItem?.addObserver(this, forKeyPath = "playbackBufferEmpty", options = NSKeyValueObservingOptions.new, context = null);
this.player.currentItem?.addObserver(this, forKeyPath = "playbackLikelyToKeepUp", options = NSKeyValueObservingOptions.new, context = null);
}
observeValue(@argumentLabel("forKeyPath") keyPath?: string, @argumentLabel("of") object?: any, change?: [NSKeyValueChangeKey : any], context?: UnsafeMutableRawPointer) {
// let playerItem:AVPlayerItem = object as! AVPlayerItem
let playerItem:AVPlayerItem = object as AVPlayerItem
// let playerItem:AVPlayerItem = object
if (keyPath == "status") {
switch (playerItem?.status) {
case AVPlayerItem.Status.readyToPlay://准备播放
// this.canDraggingFlag = true
// this.totalDuration = CMTimeGetSeconds(playerItem.duration)
// this.prepareToPlayBlock?(Float(this.totalDuration))
// if (this.timeOffset>0) {
// let time:CMTime = CMTimeMakeWithSeconds(this.timeOffset, preferredTimescale: 1 * Int32(NSEC_PER_SEC))
// this.player.seek(to: time, toleranceBefore: CMTime.zero, toleranceAfter:CMTime.zero)
// }
// this.updatePlayProgress()//播放进度
//this.playAudio()
[break;]
case AVPlayerItem.Status.failed:
// this.completePlayBlock?(false)
[break;]
case AVPlayerItem.Status.unknown:
[break;]
default :
[break;]
}
} else if (keyPath == "loadedTimeRanges"){//获取最新缓存的区间
let bufferInterval:TimeInterval = this.bufferedDuration()
// this.bufferingBlock?(Float(bufferInterval))
} else if (keyPath == "playbackBufferEmpty"){//正在缓存视频请稍等
} else if (keyPath == "playbackLikelyToKeepUp"){//缓存好了继续播放
}
}
//播放进度
updatePlayProgress() {
this.player.addPeriodicTimeObserver(interval = CMTimeMake(value = 1, timescale = 1), queue = DispatchQueue.main, block = (time: CMTime) : void => {
//当前正在播放的时间
this.currentTime = CMTimeGetSeconds(time)
// this.playingBlock?(this.currentTime,Float(this.currentTime))
})
}
//MARK:播放完毕
@objc audioPlayCompletion() {
if (this.player.currentItem?.status == AVPlayerItem.Status.readyToPlay) {
this.player.seek(time = CMTime.zero, completionHandler = () : void => {
// this.completePlayBlock?(true)
})
}
}
//MARK:计算缓冲进度
bufferedDuration() : TimeInterval {
let loadTimeArray = this.playerItem!.loadedTimeRanges
//获取最新缓存的区间
// let newTimeRange : CMTimeRange = loadTimeArray.first as! CMTimeRange
let newTimeRange : CMTimeRange = loadTimeArray.first as CMTimeRange
// let newTimeRange : CMTimeRange = loadTimeArray.first!.timeRangeValue
let startSeconds = CMTimeGetSeconds(newTimeRange.start);
let durationSeconds = CMTimeGetSeconds(newTimeRange.duration);
let totalBuffer = startSeconds + durationSeconds;//缓冲总长度
//print("当前缓冲时间:\(totalBuffer)")
return totalBuffer
}
//MARK:释放 播放器
destroyPlayer() {
this.player.pause()
this.currentTime = 0.0
this.player.currentItem?.cancelPendingSeeks()
this.player.currentItem?.asset.cancelLoading()
this.player.replaceCurrentItem(with = null)
}
//MARK:移除通知
removeObserverFromPlayer() {
this.player.currentItem?.removeObserver(this, forKeyPath = "status")
this.player.currentItem?.removeObserver(this, forKeyPath = "loadedTimeRanges")
this.player.currentItem?.removeObserver(this, forKeyPath = "playbackBufferEmpty")
this.player.currentItem?.removeObserver(this, forKeyPath = "playbackLikelyToKeepUp")
NotificationCenter.default.removeObserver(this, name = NSNotification.Name.AVPlayerItemDidPlayToEndTime, object = null)
}
}
const AudioPlayerTool: NetAudioPlayerTool = new NetAudioPlayerTool()
/**
* 创建Player
*/
export function createPlayer(url: string) {
AudioPlayerTool.createPlayer(url)
}
/**
* 开始播放
*/
export function playAudio() {
AudioPlayerTool.playAudio()
}
/**
* 暂停播放
*/
export function pauseAudio() {
AudioPlayerTool.pauseAudio()
}
调用代码:
// index.vue
import {
createPlayer,
playAudio
} from "@/uni_modules/uts-audio-player"
export default {
mounted() {
createPlayer('https://qn.wanhaoi.com/chat_voices/20230606/560bd4696bf5dcbab7d0e4512a389d3c/nDfeJYpN8jsGGx58rnRHpkDXjthBAd82.mp3')
}
}
7***@qq.com (作者)
上传了示例代码
2023-06-09 09:56