swift - 如何在 AVPlayer 中打开数据而不是标准 url

标签 swift video avplayer avplayerviewcontroller

如何在 AVPlayer 中打开数据视频文件而不是标准 url?

let videoURL = URL(string: "https://example")

但我只有 URL 而不是

var dataTs : Data = Data()

我必须把它放在 AVPlayerController 中

let player = AVPlayer(url: videoURL!)
playerViewController.player = player

最佳答案

您不需要将数据写入临时文件。您可以改用命名管道。它与写入临时文件非常相似,只是它不需要任何存储空间并且速度更快。

如果您不熟悉命名管道,它们并没有那么复杂。它们看起来和行为都像文件,但文件中的数据不是来自存储介质,而是来自另一个进程或线程。它们是通过一个简单的函数调用创建的,在 Swift 中看起来像这样:

mkfifo("foo", 0o666) // Note: 0o666 is Swift notation for octal values

以下是它在您的案例中的工作方式:您创建如上所示的命名管道。然后你设置一个调度队列来打开文件并将你的数据写入它。写入操作将阻塞,直到出现其他情况并打开同一文件以从中读取。发生这种情况时,您的写入操作将解除阻塞并开始将数据直接发送到传入的读取请求。

一旦您的调度设置并等待,只需像往常一样继续并传递一个指向您的命名管道的 URLAVPlayerAVPlayer 会认为它正在从文件中读取数据,但它实际上是从您的 dataTs 对象中读取数据。

您可以获得一个基本的工作版本,其中包含一个辅助函数,该函数实质上是将 Data 对象转换为 URL 以供一次性使用。这是一个 Swift 示例:

func setupNamedPipe(withData data: Data) -> URL?
{
    // Build a URL for a named pipe in the documents directory
    let fifoBaseName = "avpipe"
    let fifoUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!.appendingPathComponent(fifoBaseName)

    // Ensure there aren't any remnants of the fifo from a previous run
    unlink(fifoUrl.path)

    // Create the FIFO pipe
    if mkfifo(fifoUrl.path, 0o666) != 0
    {
        print("Failed to create named pipe")
        return nil
    }

    // Run the code to manage the pipe on a dispatch queue
    DispatchQueue.global().async
    {
        print("Waiting for somebody to read...")
        let fd = open(fifoUrl.path, O_WRONLY)
        if fd != -1
        {
            print("Somebody is trying to read, writing data on the pipe")
            data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
                let num = write(fd, bytes, data.count)
                if num != data.count
                {
                    print("Write error")
                }
            }

            print("Closing the write side of the pipe")
            close(fd)
        }
        else
        {
            print("Failed to open named pipe for write")
        }

        print("Cleaning up the named pipe")
        unlink(fifoUrl.path)
    }

    return fifoUrl
}

以下是您将如何使用它:

var dataTs : Data = Data() // ...your data...

if let videoURL = setupNamedPipe(withData: dataTs)
{
    let player = AVPlayer(url: videoURL)
    playerViewController.player = player

    // ...do stuff...
}

关于swift - 如何在 AVPlayer 中打开数据而不是标准 url,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48229690/

相关文章:

xcode - fatal error : unexpectedly found nil while unwrapping an Optional value in swift(SKProduct)

video - FFMPEG 拜耳过滤器

c++ - ISampleGrabber 可以将视频帧转换为特定的媒体类型吗?

ios - 如何让 Airplay 与加密的 HTTPS 流媒体一起工作?

swift - 再次点击按钮如何反转事务,使事务的读写不增加?

ios - 动态约束更新

ios - 我如何知道 AVPlayer 视频何时结束?

ios - iOS8 中的 AVPlayerItem addobserver 问题

swift - 如何从 UIViewController 到场景

android - Mediarecorder 视频 RTP/RTSP 流!