Using AvAssetWriter with named pipes in iOS

I'd like to have the output of AVAssetWriter dump to a named pipe so that I can do further downstream processing of it using third-party tools. Everything looks like it should work but it doesn't.


First, I generate an NSURL and set the file resource type as a named pipe


        let url = NSURL(fileURLWithPath: path)
        do {
            try url.setResourceValue(NSURLFileResourceTypeNamedPipe, forKey:NSURLFileResourceTypeKey)
        } catch {
            print("failed to create the named pipe")
            return
        }


Next, I create an instance of AVAssetWriter using this url and start it up. However, AVAssetWriter seems to ignore the resource designation and just creates a regular file. I can see this when I dump the status of the url object.


print(try! url.resourceValuesForKeys([NSURLFileResourceTypeKey]))
["NSURLFileResourceTypeKey": NSURLFileResourceTypeRegular]


Is there any way to make this work? Alternative suggestions?

I'm still at a loss for ideas here. Suggestions would be greatly appreciated. Also, if there's an alternative place I should post my question, let me know.

Yes, a URL isn't the thing it's a reference to, so it's not surprising that AVAssetWriter just creates a regular file.


I don't think there's any magic available here. You're going to have to create a named pipe yourself, which is a UNIXy thing that's outside my competence, but it looks like the mkfifo () is the correct function to do it. (However, since your 'path' variable is presumably a String or NSString, make sure you pass path.fileSystemRepresentation to the UNIX function, to do any translation between character sets that's necessary.)


If that succeeds, then proceed with creating the url exactly as you've already done. AVAssetWriter should then see that the "file" exists at your "path" and not try to create it.


Of course, it's quite possible that AVAssetWriter will refuse to write to something that's not a regular file, but you could be lucky…

Yeah. I tried that. AVAssetWriter fails because it wants to create the file and not just write to it.


Adding...

        let res = mkfifo(path, 0o666)
        if (res != 0) {
            print("failed to create named pipe")
            return
        }

        let url = NSURL(fileURLWithPath:path)
...



Is there a way to intercept the file open/creation call? I tried hooking to NSURLProtocol and passing a different scheme type; I called it "pipe:". However, AVAssetWriter wants *only* "file:" schemes. I then tried creating hooking to "file:" schemes, but that path doesn't get exercised via the NSURLProtocol mechanism.

I should have looked at the documentation first. For AVAssetWriter initialization, it says: "Writing will fail if a file already exists at URL."


It doesn't look like this can be done. (It's not even clear that AVAssetWriter writes its data sequentially, which seems like a necessary precondition for streaming or piping the result. If it was sequential, you could use a secondary thread to monitor the output file's contents and rewrite the data to a pipe.)

It is basically sequential: quicktime is designed for streaming after all. The point of using a pipe is to avoid a huge file intermediate file being generated in the file system. I see no technical reason why I can't use a named pipe.

AVFoundation tends to have blind spots like this, where it just doesn't support something that doesn't (seem to) involve much extra difficulty. The best you can do is submit a bug report asking for the functionality you want. If you're convincing, you might see new functionality in as little as a year or two. 😉


A similar limitation exists on the input side, where if you have data that's not in a distinct file, there's no way to get AVFoundation to read it.


OTOH, I should add that it might be a performance-related decision, to restrict input and output to some very basic mechanisms, such as the disk file system. I really don't know.


It's probably worth submitting the bug report anyway. It serves as a vote for functionality that other people might want, and — you never know — the response might suggest an alternative way of achieving what you're trying to do.

Using AvAssetWriter with named pipes in iOS
 
 
Q