Repository: streamlink/streamlink

Issue:
Unable to use --player-fifo with MPV
Streamlink 2.0.0
mpv 0.33.0-76-g93066ff12f Copyright © 2000-2020 mpv/MPlayer/mplayer2 projects

```
streamlink --player-fifo https://www.twitch.tv/channelName best
[cli][info] Found matching plugin twitch for URL https://www.twitch.tv/channelName 
[cli][info] Available streams: audio_only, 160p (worst), 360p, 480p, 720p, 720p60, 1080p60 (best)
[cli][info] Opening stream: 1080p60 (hls)
[cli][info] Creating pipe streamlinkpipe-1140
[cli][info] Starting player: "c:\Programs\MPV\mpv.exe"
error: Failed to start player: "c:\Programs\MPV\mpv.exe" (Process exited prematurely)
[cli][info] Closing currently open stream...
```

Works normally without FIFO


Discussion:
Does it work with VLC?

https://raw.githubusercontent.com/streamlink/streamlink/master/.github/ISSUE_TEMPLATE/bug_report.md

https://streamlink.github.io/cli.html#cmdoption-loglevel
https://streamlink.github.io/cli.html#cmdoption-verbose-player
> Does it work with VLC?

I dont have VLC but I've tried mplayer and it wont work too.

Provided log **IS** a verbose output, it is exactly the same as normal, there is no extra info. It just dies,
> Provided log IS a verbose output, it is exactly the same as normal, there is no extra info. It just dies,

That's not what the command line you have provided above seems to indicate.
> it is exactly the same as normal, there is no extra info. It just dies,


Stop being so immature and dense. Your documentation clearly states MPV works with Named Pipe when in reality it isnt, which is a misleading lie.

```
streamlink --verbose-player https://www.twitch.tv/yuushi_1234 best
[cli][info] Found matching plugin twitch for URL https://www.twitch.tv/yuushi_1234
[cli][info] Available streams: audio_only, 160p (worst), 360p, 480p, 720p60, 1080p60 (best)
[cli][info] Opening stream: 1080p60 (hls)
[cli][info] Starting player: "c:\Programs\MPV\mpv.exe"
[cli][info] Player closed
[cli][info] Stream ended
[cli][info] Closing currently open stream...

streamlink --verbose-player --player-fifo https://www.twitch.tv/yuushi_1234 best
[cli][info] Found matching plugin twitch for URL https://www.twitch.tv/yuushi_1234
[cli][info] Available streams: audio_only, 160p (worst), 360p, 480p, 720p60, 1080p60 (best)
[cli][info] Opening stream: 1080p60 (hls)
[cli][info] Creating pipe streamlinkpipe-9796
[cli][info] Starting player: "c:\Programs\MPV\mpv.exe"
error: Failed to start player: "c:\Programs\MPV\mpv.exe" (Process exited prematurely)
[cli][info] Closing currently open stream...
```
There seems to be an issue with Streamlink's named pipe implementation on Windows. Neither MPV nor VLC is able to read from it. The named pipe implementation is working fine on \*nix.
https://github.com/streamlink/streamlink/blob/164b2579262a72bb291bd641309b703556878332/src/streamlink/utils/named_pipe.py

@Kein This thread was closed and tagged with "does not meet requirements" because you were (still) not able to provide a proper debug log with the necessary details, which the issue template is explicitly asking for. Remember that this is a free open source software project with volunteers working on it in their free time for fun, and the more details you provide, the easier it is for reproducing and fixing bugs. I'm giving you the first and last warning to watch your tone and not harass/insult any maintainers or contributors here.

----

```
$ streamlink -l debug -v --player-fifo -p ./mpv-x86_64-20210214-git-93066ff/mpv.exe twitch.tv/esl_csgo best
[cli][debug] OS:         Windows 10
[cli][debug] Python:     3.8.1
[cli][debug] Streamlink: 2.0.0+45.g164b257
[cli][debug] Requests(2.24.0), Socks(1.7.1), Websocket(0.57.0)
[cli][info] Found matching plugin twitch for URL twitch.tv/esl_csgo
[plugins.twitch][debug] Getting live HLS streams for esl_csgo
[utils.l10n][debug] Language code: en_DE
[cli][info] Available streams: audio_only, 160p (worst), 360p, 480p, 720p, 720p60, 1080p60 (best)
[cli][info] Opening stream: 1080p60 (hls)
[stream.hls][debug] Reloading playlist
[stream.hls][debug] First Sequence: 10328; Last Sequence: 10344
[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 10342; End Sequence: None
[stream.hls][debug] Adding segment 10342 to queue
[cli][debug] Pre-buffering 8192 bytes
[stream.hls][debug] Adding segment 10343 to queue
[stream.hls][debug] Adding segment 10344 to queue
[stream.hls][debug] Download of segment 10342 complete
[cli][info] Creating pipe streamlinkpipe-1412
[cli][info] Starting player: ./mpv-x86_64-20210214-git-93066ff/mpv.exe
[cli.output][debug] Opening subprocess: ./mpv-x86_64-20210214-git-93066ff/mpv.exe --force-media-title=twitch.tv/esl_csgo \\.\pipe\streamlinkpipe-1412
[stream.hls][debug] Download of segment 10343 complete
[stream.hls][debug] Download of segment 10344 complete
[file] Cannot open file '\\.\pipe\streamlinkpipe-1412': Resource temporarily unavailable
Failed to open \\.\pipe\streamlinkpipe-1412.

Exiting... (Errors when loading file)
error: Failed to start player: ./mpv-x86_64-20210214-git-93066ff/mpv.exe (Process exited prematurely)
[cli][info] Closing currently open stream...
[stream.segmented][debug] Closing worker thread
[stream.segmented][debug] Closing writer thread
```

```
$ streamlink -l debug -v --player-fifo -p /c/Program\ Files/VideoLAN/VLC/vlc.exe twitch.tv/esl_csgo best
[cli][debug] OS:         Windows 10
[cli][debug] Python:     3.8.1
[cli][debug] Streamlink: 2.0.0+45.g164b257
[cli][debug] Requests(2.24.0), Socks(1.7.1), Websocket(0.57.0)
[cli][info] Found matching plugin twitch for URL twitch.tv/esl_csgo
[plugins.twitch][debug] Getting live HLS streams for esl_csgo
[utils.l10n][debug] Language code: en_DE
[cli][info] Available streams: audio_only, 160p (worst), 360p, 480p, 720p, 720p60, 1080p60 (best)
[cli][info] Opening stream: 1080p60 (hls)
[stream.hls][debug] Reloading playlist
[stream.hls][debug] First Sequence: 10535; Last Sequence: 10550
[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 10548; End Sequence: None
[stream.hls][debug] Adding segment 10548 to queue
[cli][debug] Pre-buffering 8192 bytes
[stream.hls][debug] Adding segment 10549 to queue
[stream.hls][debug] Adding segment 10550 to queue
[stream.hls][debug] Download of segment 10548 complete
[cli][info] Creating pipe streamlinkpipe-6428
[cli][info] Starting player: C:/Program Files/VideoLAN/VLC/vlc.exe
[cli.output][debug] Opening subprocess: C:/Program Files/VideoLAN/VLC/vlc.exe --input-title-format twitch.tv/esl_csgo \\.\pipe\streamlinkpipe-6428
[stream.hls][debug] Download of segment 10549 complete
[stream.hls][debug] Download of segment 10550 complete
[cli][debug] Writing stream to output
[000001407d7b73f0] main libvlc: Running vlc with the default interface. Use 'cvlc' to use vlc without interface.
[000001407f2cf1c0] dvdnav demux error: Could not open \\.\pipe\streamlinkpipe-6428 with libdvdcss.
[000001407f2cf1c0] dvdnav demux error: Can't open \\.\pipe\streamlinkpipe-6428 for reading
[000001407f2cf1c0] dvdnav demux error: vm: failed to open/read the DVD
[000001407f2c74e0] filesystem stream error: cannot open file \\.\pipe\streamlinkpipe-6428 (Invalid argument)
[stream.hls][debug] Reloading playlist
[stream.hls][debug] Adding segment 10551 to queue
[stream.hls][debug] Adding segment 10552 to queue
[stream.hls][debug] Adding segment 10553 to queue
[stream.hls][debug] Adding segment 10554 to queue
[stream.hls][debug] Download of segment 10551 complete
[cli][info] Player closed
[stream.segmented][debug] Closing worker thread
[stream.segmented][debug] Closing writer thread
[cli][info] Stream ended
[stream.hls][debug] Download of segment 10552 complete
[cli][info] Closing currently open stream...
```

```
$ streamlink -l debug --player-fifo -v -p mpv twitch.tv/esl_csgo best
[cli][debug] OS:         Linux-5.11.0-2-git-x86_64-with-glibc2.33
[cli][debug] Python:     3.9.1
[cli][debug] Streamlink: 2.0.0+45.g164b257
[cli][debug] Requests(2.25.1), Socks(1.7.1), Websocket(0.57.0)
[cli][info] Found matching plugin twitch for URL twitch.tv/esl_csgo
[plugins.twitch][debug] Getting live HLS streams for esl_csgo
[utils.l10n][debug] Language code: en_US
[cli][info] Available streams: audio_only, 160p (worst), 360p, 480p, 720p, 720p60, 1080p60 (best)
[cli][info] Opening stream: 1080p60 (hls)
[stream.hls][debug] Reloading playlist
[stream.hls][debug] First Sequence: 10658; Last Sequence: 10673
[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 10671; End Sequence: None
[stream.hls][debug] Adding segment 10671 to queue
[cli][debug] Pre-buffering 8192 bytes
[stream.hls][debug] Adding segment 10672 to queue
[stream.hls][debug] Adding segment 10673 to queue
[stream.hls][debug] Download of segment 10671 complete
[cli][info] Creating pipe streamlinkpipe-511177
[cli][info] Starting player: mpv
[cli.output][debug] Opening subprocess: mpv --force-media-title=twitch.tv/esl_csgo --cache=no /tmp/streamlinkpipe-511177
[stream.hls][debug] Download of segment 10672 complete
[stream.hls][debug] Download of segment 10673 complete
[cli][debug] Writing stream to output
 (+) Video --vid=1 (h264 1920x1080 59.940fps)
 (+) Audio --aid=1 (aac 2ch 48000Hz)
AO: [pulse] 48000Hz stereo 2ch float
VO: [gpu] 1920x1080 yuv420p

Exiting... (Quit)
[cli][info] Player closed
[stream.segmented][debug] Closing worker thread
[stream.segmented][debug] Closing writer thread
[cli][info] Stream ended
[cli][info] Closing currently open stream...
```
This should be mentioned on the Documentation page for Players that Named Pipe does not work on Windows.
No, this is a bug and needs to be fixed.
When did last time named pipe work on Windows?
It is not just broken it is super broken. Every time I try to start streamlink with namedpipe, it destroys total OS I/O, any app that uses named pipe slows to a crawl and starts to use 20% of my CPU.
It might not be possible on Windows 10 any more.
> Windows 10, version 1709:  Pipes are only supported within an app-container; ie, from one UWP process to another UWP process that's part of the same app. Also, named pipes must use the syntax "\\\\.\pipe\LOCAL\\" for the pipe name.

It doesn't appear that launching `mpv`, or `VLC` via `python` creates those subprocesses in the same App. For example, if you use PowerShell to launch streamlink, then PowerShell is the App that contains streamlink, but the player process will be a separate App. 

![Screenshot 2021-02-18 at 03 12 09](https://user-images.githubusercontent.com/16033421/108294944-19b19180-7197-11eb-9d34-4dbb844905f4.png) ![Screenshot 2021-02-18 at 03 13 13](https://user-images.githubusercontent.com/16033421/108295024-3f3e9b00-7197-11eb-8e14-e77bdfe9d836.png)

@Kein as you didn't post the debug logs I cannot tell what version of Windows you are using, but I'm going to assume it's Windows 10, perhaps you can post the output from `winver` to confirm. 

@bastimeyer we may need to update the documentation, or disable `--player-fifo` for Windows with a warning. 
> You can only use a named pipe to communicate either between two UWP processes that are part of the same app, or between two non-UWP processes. I don't believe NtFsControlFile will work at all in a UWP process

Looks like restriction is applied only to UWP
That does appear to be true. I will continue to investigate. Is there any specific reason that you need to use named pipes @Kein?
I don't understand the question. Is this a bug or a limitation of the platform? If it is a bug that for some reason went unaddressed for 2+ years then it should be fixed, if it is intended limitation then documentation, that was incorrect for 2+ years - should be fixed.

There is no other ways around it.
It used to work, it doesn't any more. An issue has arisen somewhere along the way which has rendered the feature inoperable, I do not know how long it has been broken - you're the first to report it. 

This issue will either be fixed or the feature will be removed. I cannot think of a reason why you would _need_ to use named pipes in Windows and I don't think that many users would miss the feature if it were gone. That is why I asked, if you have a reason to use named pipes in Windows then I will put extra effort in to resolving it. 

Please remember that this is a non-commercial project, people give their free-time to work on it. Your comments read like you are making demands, I'm sure you didn't mean it that way - but people will be more inclined to help if you're nice. 
@beardypig If there's no way around the restriction, we can add a note to the documentation or remove/disable it for win10. The whole NamedPipe class should ideally be split up though if there's a way to fix this, because currently it's checking the OS type on every open/write/close call.

https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipe-security-and-access-rights

> Windows security enables you to control access to named pipes. For more information about security, see Access-Control Model.
> You can specify a security descriptor for a named pipe when you call the CreateNamedPipe function. The security descriptor controls access to both client and server ends of the named pipe.

https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea

> ```
> HANDLE CreateNamedPipeA(
>   LPCSTR                lpName,
>   DWORD                 dwOpenMode,
>   DWORD                 dwPipeMode,
>   DWORD                 nMaxInstances,
>   DWORD                 nOutBufferSize,
>   DWORD                 nInBufferSize,
>   DWORD                 nDefaultTimeOut,
>   LPSECURITY_ATTRIBUTES lpSecurityAttributes
> );
> ```

> `lpSecurityAttributes`
> A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new named pipe and determines whether child processes can inherit the returned handle. If lpSecurityAttributes is NULL, the named pipe gets a default security descriptor and the handle cannot be inherited. The ACLs in the default security descriptor for a named pipe grant full control to the LocalSystem account, administrators, and the creator owner. They also grant read access to members of the Everyone group and the anonymous account.

`lpSecurityAttributes` is currently set to `NULL`/`None`:
https://github.com/streamlink/streamlink/blob/164b2579262a72bb291bd641309b703556878332/src/streamlink/utils/named_pipe.py#L41
I dont have time to test it right now, but I wonder if running streamlink compiled executable (that is how it is distributed via pip on Windows) in Windows 7 compatibility mode can make it work (since python interpreter executable will inherit environment from streamlink.exe). There is something wrong with the pipe python creates, it is possible windows treats it as UWP one, I cant even check its flags via SysInternal's **accesschk** for example. There is simply no access to that pipe even under SYSTEM account.
@Kein You still haven't answered the question Beardypig asked. What is your use case for the named pipe? 
Dunno how relevant it will be but here is surface stack snapshot for **explorer.exe** bugged thread after streamlink creates pipe via python which VLC fails to open:

```
ntoskrnl.exe!KeSynchronizeExecution+0x5b66
ntoskrnl.exe!KeWaitForMutexObject+0x1460
ntoskrnl.exe!KeWaitForMutexObject+0x98f
ntoskrnl.exe!KeWaitForMutexObject+0x233
ntoskrnl.exe!ExWaitForRundownProtectionRelease+0x7dd
ntoskrnl.exe!KeWaitForMutexObject+0x3a29
ntoskrnl.exe!KeSynchronizeExecution+0x3140
KERNELBASE.dll!CharNextW+0x2
LINKINFO.dll!DestroyLinkInfo+0x1787
LINKINFO.dll!DestroyLinkInfo+0x1104
windows.storage.dll!SHGetFileInfoW+0x24c8
windows.storage.dll!SHGetFileInfoW+0x1f95
windows.storage.dll!SHGetFileInfoW+0xda1
windows.storage.dll!GetRegDataDrivenCommandWithAssociation+0x529d
windows.storage.dll!GetRegDataDrivenCommandWithAssociation+0x5516
windows.storage.dll!DetermineFolderDestinationParentAppID+0x7ce
windows.storage.dll!DetermineFolderDestinationParentAppID+0x40c
windows.storage.dll!DetermineFolderDestinationParentAppID+0x2e1
windows.storage.dll!CTaskAddDoc_Create+0x1671
windows.storage.dll!CTaskAddDoc_Create+0x14e7
windows.storage.dll!CTaskAddDoc_Create+0xad0
windows.storage.dll!CTaskAddDoc_Create+0x80e
windows.storage.dll!SHGetFolderPathAndSubDirW+0x3211
windows.storage.dll!CShellItemArray_CreateInstance+0x71ac
windows.storage.dll!CShellItemArray_CreateInstance+0x6df1
windows.storage.dll!CShellItemArray_CreateInstance+0x69c4
shcore.dll!DllCanUnloadNow+0x256
ntdll.dll!RtlRegisterWait+0x5b3
ntdll.dll!LdrAccessResource+0x194a
KERNEL32.DLL!BaseThreadInitThunk+0x14
ntdll.dll!RtlUserThreadStart+0x21
```

Interestingly enough the bug only reproducible with VLC, MPV just instant dies and the bug does not happen it seems.
I've tested it with Compatibility mode - it still creates bugged pipe
@Kein You have still not answered the original question. What is your use case for the named pipe? Unless we get an actual reason we're going to remove it since it's pretty pointless on Windows.
@bastimeyer 
> If there's no way around the restriction

Here is primitive working example I've tested:
https://jonathonreinhart.com/posts/blog/2012/12/13/named-pipes-between-c-and-python/

it works just fine. After numerous testing I conclude there is something broken about the pipe python creates through winapi (windll).
@beardypig Let's ditch the feature.
fwiw this is the original PR that added named pipe support: https://github.com/chrippa/livestreamer/pull/24
@beardypig Thanks for finding that. Seems more like a limitation of specific players and a very limited use case on Windows devices.
Yeah, I didn't test to see if it was still a limitation with the mplayer forks though. I have tried for quite a while to get it working with VLC but I haven't had much luck yet.

I got it to work with VLC (this was actually reported before in #739).

```
streamlink.exe -v -l debug --player-fifo --player-args "stream://\{playerinput}" twitch.tv/sovietwomble best
```

I haven't managed to get it to work in MPV though, I don't know that MPV supports named pipes in Windows because it treats them as regular files and it would need to do something special... maybe there is an option, but I cannot find it. I suspect it would work with MPlayer, but I haven't tested it yet. This is after I totally rewrote the `NamedPipe` class for Windows using non-blocking overlapping IO calls in an attempt to get it to work... le sigh.

@Kein 
> Your documentation clearly states MPV works with Named Pipe when in reality it isnt

Could you point out where it says MPV works with named pipes in the documentation, I couldn't find it. It's so we can fix the docs, we could also add that workaround for VLC (or perhaps implement it, but it's pretty specific; Windows + Named Pipe + VLC > some specific version).
I will test MPV and Mplayer later with generic named pipe where I will feed it byte stream of some video file.

>Could you point out where it says MPV works with named pipes in the documentation

That is incorretly worded question. I never stated that documentation says "MPV works with named pipes on Windows", I said "Documentation states VLC, Mplayer and MPV work with streamlink and named pipes but there are no clearly visible remarks that it is only for Linux/Unix". 
Here:
https://streamlink.github.io/players.html

The table just states "Named pipes" and "Yes" for aforementioned players. Windows does have Named Pipes. There are no special platform remarks. Therefore, as an end user, I've assumed "streamlink+selected players" will work with Named Pipes. They dont. A remark is warranted fo whole "Named Pipe" row that Windows platform is an exclusion.

@Kein I literally quoted what you wrote in a previous comment. I also didn't say you did say it worked on Windows, I asked where you it says it works with named pipes because I couldn't remember where it was in the docs. 

Anyway, it does work on Windows with MPV - you just need the correct incantation. 
```
streamlink.exe -v -l debug --player-fifo -p mpv --player-args "file://{playerinput}" twitch.tv/sovietwomble best
```

----

@bastimeyer 
We can update the documentation to include a footnote for VLC and MPV using named pipes on Windows. We could also detect if the user is using named Pipes and Windows and direct them to the documentation notes with an `INFO` log message or something. 

The way that Named Pipes have been handled by these players has changed over time, and this has been a frustrating issue to debug... 
@beardypig good job finding a solution. :+1: 

What we could do instead of adding a note to the docs is change the value of `filename` in `PlayerOutput._create_arguments` depending on the OS and player being used while using a named pipe, so that it automatically sets the right player input argument, and the user doesn't have to change their streamlink command.

The player already gets detected for the `--title` arg, so there shouldn't be any problems here, and regarding the different VLC versions, I don't think we should care about the old versions. [The comment in the linked PR](https://github.com/streamlink/streamlink/pull/739#issuecomment-294462397) says that the issue was found in "both VLC 2.2.4 and VLC 3.0.0", which means it could have also been changed prior to `2.2.4` (which was released mid-2016), but got unnoticed. By the way, the [VLC wiki says](https://wiki.videolan.org/Uncommon_uses/) that named pipes can be read from `fd://nameofpipe`. Not sure where the `stream://nameofpipe` solution of the PR comes from. Are there any version concerns for mpv?
There probably should be a way to specify player args in **streamlinkrc** a-la:
`player="c:\Programs\VLC\vlc.exe args"`

This could be useful here
@bastimeyer we could do it for MPV and VLC as well as adding a generic note in the docs. I didn't want to make it too complicated for such an under utilised feature. 
I could not get `fd://nameofpipe` to work in VLC (I think this only applies to POSIX), only `stream://\\\.\pipe\nameofpipe` (nb. there are 3 `\`s instead of the usual 2). I don't know if it worked before in MPV on Windows or it's just that no one ever tried it, I think they it has always required `file://` to work on MPV on Windows. 

@Kein this is already possible, you just put `player-args=...` in the config file ([CLI docs](https://streamlink.github.io/cli.html#configuration-file)).


> we could do it for MPV and VLC as well as adding a generic note in the docs.

That is probably the best solution. The whole `Output/PlayerOutput` and `NamedPipe` implementation is unfortunately a bit messy right now and it should probably be refactored a bit before adding more OS- and player-related logic. I can open a PR with a refactor of `NamedPipe` later today that splits up the logic between win32 and \*nix, but there's another issue I've noticed on \*nix systems.

When the `output.open()` call raises an `OSError` in `streamlink_cli.main.output_stream`, eg. when the player set by the user doesn't exist, then the output won't be closed again before `console.error()` gets called, which means that the fifo in the system's tempdir does not get removed. It's not possible to call `output.close()` in the except block though, as the base `Output` class will prevent this, because the output hasn't been successfully opened yet.

```bash
streamlink --player-fifo --player /dev/null URL STREAM
ls /tmp/streamlinkpipe-*
```

> I could not get `fd://nameofpipe` to work in VLC

Ok, I didn't try it myself, just found it in their wiki.

----

https://github.com/streamlink/streamlink/issues/3568#issuecomment-782787642

> twitch.tv/sovietwomble

:+1: 
@beardypig 
> Is there any specific reason that you need to use named pipes @Kein?

I was investigating latency. Unlike sockets, pipes are are built on top of shared memory segments and have less overhead and in general way faster locally.
https://docs.microsoft.com/en-us/windows/win32/ipc/pipes

@bastimeyer a CLI rewrite is long overdue ;) Actually a lot of things could do with a rewrite... 

@Kein was it noticeable? By default STDOUT and STDIN are used to communicate between streamlink and the player process, generally speaking these are pretty fast - I don't know enough about Windows programming to say for sure if they implemented using shared memory or not. 
> was it noticeable?

Havent had time to test properly since it was bugged. my current measurements just a few ms which could be margin of error.

Resolving patch:
diff --git a/src/streamlink_cli/output.py b/src/streamlink_cli/output.py
--- a/src/streamlink_cli/output.py
+++ b/src/streamlink_cli/output.py
@@ -180,6 +180,11 @@ def _mpv_title_escape(cls, title_string):
     def _create_arguments(self):
         if self.namedpipe:
             filename = self.namedpipe.path
+            if is_win32:
+                if self.player_name == "vlc":
+                    filename = f"stream://\\{filename}"
+                elif self.player_name == "mpv":
+                    filename = f"file://{filename}"
         elif self.filename:
             filename = self.filename
         elif self.http:


Test patch:
diff --git a/tests/test_cmdline_player_fifo.py b/tests/test_cmdline_player_fifo.py
new file mode 100644
--- /dev/null
+++ b/tests/test_cmdline_player_fifo.py
@@ -0,0 +1,45 @@
+import unittest
+from unittest.mock import Mock, patch
+
+from streamlink.compat import is_win32
+from tests.test_cmdline import CommandLineTestCase
+
+
+@unittest.skipIf(is_win32, "test only applicable in a POSIX OS")
+@patch("streamlink_cli.main.NamedPipe", Mock(return_value=Mock(path="/tmp/streamlinkpipe")))
+class TestCommandLineWithPlayerFifoPosix(CommandLineTestCase):
+    def test_player_fifo_default(self):
+        self._test_args(
+            ["streamlink", "--player-fifo",
+             "-p", "any-player",
+             "http://test.se", "test"],
+            ["any-player", "/tmp/streamlinkpipe"]
+        )
+
+
+@unittest.skipIf(not is_win32, "test only applicable on Windows")
+@patch("streamlink_cli.main.NamedPipe", Mock(return_value=Mock(path="\\\\.\\pipe\\streamlinkpipe")))
+class TestCommandLineWithPlayerFifoWindows(CommandLineTestCase):
+    def test_player_fifo_default(self):
+        self._test_args(
+            ["streamlink", "--player-fifo",
+             "-p", "any-player.exe",
+             "http://test.se", "test"],
+            "any-player.exe \\\\.\\pipe\\streamlinkpipe"
+        )
+
+    def test_player_fifo_vlc(self):
+        self._test_args(
+            ["streamlink", "--player-fifo",
+             "-p", "C:\\Program Files\\VideoLAN\\vlc.exe",
+             "http://test.se", "test"],
+            "C:\\Program Files\\VideoLAN\\vlc.exe --input-title-format http://test.se stream://\\\\\\.\\pipe\\streamlinkpipe"
+        )
+
+    def test_player_fifo_mpv(self):
+        self._test_args(
+            ["streamlink", "--player-fifo",
+             "-p", "C:\\Program Files\\mpv\\mpv.exe",
+             "http://test.se", "test"],
+            "C:\\Program Files\\mpv\\mpv.exe --force-media-title=http://test.se file://\\\\.\\pipe\\streamlinkpipe"
+        )