如何在 AVPlayer 中打开数据而不是标准 url
How to open data instead standart url in AVPlayer
如何在 AVPlayer 中打开数据视频文件而不是标准 url?
let videoURL = URL(string: "https://example")
但是 URL 我只有
var dataTs : Data = Data()
我必须把它放在 AVPlayerController
let player = AVPlayer(url: videoURL!)
playerViewController.player = player
您不需要将数据写入临时文件。您可以改用命名管道。它与写入临时文件非常相似,只是它不需要任何存储空间 space 并且速度更快。
如果您不熟悉命名管道,它们并没有那么复杂。它们看起来和行为都像文件,但文件中的数据不是来自存储介质,而是来自另一个进程或线程。它们是通过一个简单的函数调用创建的,在 Swift:
中看起来像这样
mkfifo("foo", 0o666) // Note: 0o666 is Swift notation for octal values
以下是它在您的情况下的工作方式:您创建如上所示的命名管道。然后你设置一个调度队列来打开文件并将你的数据写入它。写入操作将阻塞,直到出现其他情况并打开同一文件以从中读取。发生这种情况时,您的写入操作将解除阻塞并开始将数据直接发送到传入的读取请求。
一旦您的调度设置并等待,就像往常一样继续并传入一个指向您的命名管道的 URL
到 AVPlayer
。 AVPlayer
会认为它正在从文件中读取,但它实际上是从您的 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...
}
如何在 AVPlayer 中打开数据视频文件而不是标准 url?
let videoURL = URL(string: "https://example")
但是 URL 我只有
var dataTs : Data = Data()
我必须把它放在 AVPlayerController
let player = AVPlayer(url: videoURL!)
playerViewController.player = player
您不需要将数据写入临时文件。您可以改用命名管道。它与写入临时文件非常相似,只是它不需要任何存储空间 space 并且速度更快。
如果您不熟悉命名管道,它们并没有那么复杂。它们看起来和行为都像文件,但文件中的数据不是来自存储介质,而是来自另一个进程或线程。它们是通过一个简单的函数调用创建的,在 Swift:
中看起来像这样mkfifo("foo", 0o666) // Note: 0o666 is Swift notation for octal values
以下是它在您的情况下的工作方式:您创建如上所示的命名管道。然后你设置一个调度队列来打开文件并将你的数据写入它。写入操作将阻塞,直到出现其他情况并打开同一文件以从中读取。发生这种情况时,您的写入操作将解除阻塞并开始将数据直接发送到传入的读取请求。
一旦您的调度设置并等待,就像往常一样继续并传入一个指向您的命名管道的 URL
到 AVPlayer
。 AVPlayer
会认为它正在从文件中读取,但它实际上是从您的 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...
}