How i can open data video file instead standart url in AVPlayer?
let videoURL = URL(string: "https://example")
but instead URL i have only
var dataTs : Data = Data()
and i must put it in AVPlayerController
let player = AVPlayer(url: videoURL!)
playerViewController.player = player
You don't need to write the data to a temporary file. You can use a named pipe instead. It's very similar to writing to a temporary file, except that it doesn't require any storage space and it's faster.
If you're not familiar with named pipes, they aren't that complex. They look like and act like files, but rather than the data from the file coming from storage media, it's coming from another process or thread. They're created with a simple function call that looks like this in Swift:
mkfifo("foo", 0o666) // Note: 0o666 is Swift notation for octal values
Here's how it would work in your case: You create the named pipe as shown above. Then you setup a dispatch queue to open the file and write your data to it. The write operation will block until something else comes along and opens the same file to read from it. When that happens, your write operation will unblock and start sending data directly to the incoming read request.
Once your dispatch is setup and waiting, just continue along like normal and pass in a URL
that points to your named pipe to AVPlayer
. AVPlayer
will think it's reading from a file, but it's really reading the data from your dataTs
object.
You can get a basic working version with a single helper function that essentially converts a Data
object into a URL
for one-time use. Here's a Swift sample:
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
}
Here's how you would use it:
var dataTs : Data = Data() // ...your data...
if let videoURL = setupNamedPipe(withData: dataTs)
{
let player = AVPlayer(url: videoURL)
playerViewController.player = player
// ...do stuff...
}