【问题标题】:how to stream mp3 urls (iOS) in Swift?如何在 Swift 中流式传输 mp3 url (iOS)?
【发布时间】:2015-06-24 22:52:57
【问题描述】:

目前下面的代码可以流式传输本地 mp3 文件,所以如果我调用

audio.scheduleFile(NSBundle.mainBundle().URLForResource("Moon River", withExtension: "mp3")!) 它将正确播放本地文件。现在我希望能够流式传输非本地 url。

我需要做什么才能让我流式传输 mp3 网址?

class Audio: NSObject {
    var graph: AUGraph
    var filePlayerAU: AudioUnit
    var filePlayerNode: AUNode
    var outputAU: AudioUnit
    var fileID: AudioFileID
    var currentFrame: Int64

    override init () {
        graph = AUGraph()
        filePlayerAU = AudioUnit()
        filePlayerNode = AUNode()
        outputAU = AudioUnit()
        fileID = AudioFileID()
        currentFrame = 0

        super.init()

        NewAUGraph(&graph)

        // Add file player node
        var cd = AudioComponentDescription(componentType: OSType(kAudioUnitType_Generator),
                                            componentSubType: OSType(kAudioUnitSubType_AudioFilePlayer),
                                            componentManufacturer: OSType(kAudioUnitManufacturer_Apple),
                                            componentFlags: 0, componentFlagsMask: 0)
        AUGraphAddNode(graph, &cd, &filePlayerNode)

        // Add output node
        var outputNode = AUNode()

        cd.componentType = OSType(kAudioUnitType_Output)
        cd.componentSubType = OSType(kAudioUnitSubType_RemoteIO)
        AUGraphAddNode(graph, &cd, &outputNode)

        // Graph must be opened before we can get node info!
        AUGraphOpen(graph)
        AUGraphNodeInfo(graph, filePlayerNode, nil, &filePlayerAU)
        AUGraphNodeInfo(graph, outputNode, nil, &outputAU)


        AUGraphConnectNodeInput(graph, filePlayerNode, 0, outputNode, 0)
        AUGraphInitialize(graph)

        registerCallbackForAU(filePlayerAU, nil)
    }

    func scheduleFile(url: NSURL) {
        AudioFileOpenURL(url, 1, 0, &fileID)

        // Step 1: schedule the file(s)
        // kAudioUnitProperty_ScheduledFileIDs takes an array of AudioFileIDs
        var filesToSchedule = [fileID]
        AudioUnitSetProperty(filePlayerAU,
                                AudioUnitPropertyID(kAudioUnitProperty_ScheduledFileIDs),
                                AudioUnitScope(kAudioUnitScope_Global), 0, filesToSchedule,
                                UInt32(sizeof(AudioFileID)))
    }

    func scheduleRegion() {
        // Step 2: Schedule the regions of the file(s) to play
        // Swift forces us to fill out the structs completely, even if they are not used
        let smpteTime = SMPTETime(mSubframes: 0, mSubframeDivisor: 0,
                                    mCounter: 0, mType: 0, mFlags: 0,
                                    mHours: 0, mMinutes: 0, mSeconds: 0, mFrames: 0)

        var timeStamp = AudioTimeStamp(mSampleTime: 0, mHostTime: 0, mRateScalar: 0,
                                        mWordClockTime: 0, mSMPTETime: smpteTime,
                                        mFlags: UInt32(kAudioTimeStampSampleTimeValid), mReserved: 0)

        var region = ScheduledAudioFileRegion()
        region.mTimeStamp = timeStamp
        region.mCompletionProc = nil
        region.mCompletionProcUserData = nil
        region.mAudioFile = fileID
        region.mLoopCount = 0
        region.mStartFrame = currentFrame
        region.mFramesToPlay = UInt32.max

        AudioUnitSetProperty(filePlayerAU,
                                AudioUnitPropertyID(kAudioUnitProperty_ScheduledFileRegion),
                                AudioUnitScope(kAudioUnitScope_Global), 0, &region,
                                UInt32(sizeof(ScheduledAudioFileRegion)))

        // Step 3: Prime the file player
        var primeFrames: UInt32 = 0
        AudioUnitSetProperty(filePlayerAU,
                                AudioUnitPropertyID(kAudioUnitProperty_ScheduledFilePrime),
                                AudioUnitScope(kAudioUnitScope_Global), 0, &primeFrames,
                                UInt32(sizeof(UInt32)))

        // Step 4: Schedule the start time (-1 = now)
        timeStamp.mSampleTime = -1
        AudioUnitSetProperty(filePlayerAU,
                                AudioUnitPropertyID(kAudioUnitProperty_ScheduleStartTimeStamp),
                                AudioUnitScope(kAudioUnitScope_Global), 0,  &timeStamp,
                                UInt32(sizeof(AudioTimeStamp)))
    }
}

【问题讨论】:

  • 可以先获取base64服务器“data:audio/mp3;base64”,传给“NSData”,这样就可以在普通的AVPlayer上播放了。

标签: swift audiounit


【解决方案1】:

如果您想从服务器播放远程文件 (mp3)。我会考虑使用 AVPlayer()。

https://developer.apple.com/documentation/avfoundation/avplayer

这里有一个 sn-p 可能会推动您朝着正确的方向前进。当然这只是一个非常基本的例子。

func playRemoteFile() {

    let fileUrl = "http://www.foo.com/bar.mp3"
    let url = NSURL(string: fileUrl)

    var myPlayer = AVPlayer(URL: url)
    myPlayer.play()
}

【讨论】:

  • 为什么投反对票?用户询问如何从非本地 url 流式传输 mp3。我认为这意味着来自服务器。这允许。用户还要求提供来自“可信/官方”来源的答案。我认为有关 AVplayer 的苹果官方文档选中了该框。
  • 在发布到应用商店之前,请确保符合 App Store Review Guidelines 中的以下规则:-> 9.3 蜂窝网络上的音频流内容在 5 分钟内使用的容量不得超过 5MB developer.apple.com/app-store/review/guidelines
  • @NirbhayKundan 此规则不再存在。 2.5.7 蜂窝网络上超过 10 分钟的视频流媒体内容必须使用 HTTP 实时流媒体并包括基线 192 kbps HTTP 实时流媒体。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多