How to close VLC gracefully using C#

2019-07-26 10:54发布

I am running a surveillance system, and wanting to record the video from some CCTV cameras to my PC.

I can get the recording to occur using the VLC command line like this,

vlc rtsp://*username*:*password*@192.168.1.60:554/ch01/0  --qt-start-minimized --sout=#transcode{ab=128,channels=2,samplerate=44100,scodec=none}:file{dst=D:\CCTV\Concord\2019_05_24\2019-05-24_2111_C1.mp4,no-overwrite}

However I want to stop and restart the recording every half an hour so that I get files small enough that I can use.

I wrote a C# application to do this, it simply kills all VLC processes and starts new ones. It is triggered by task scheduler on the half hour.

This works when I run normal VLC instances showing in the taskbar. However I want they to be out of the way in the system tray. I can do this by adding this VLC option,

--qt-start-minimized

Which runs it under background processes if I look in task manager.

My code does this,

foreach(Process process in Process.GetProcesses().Where(x => x.ProcessName == "vlc"))
{
    Process.GetProcessById(id).CloseMainWindow();
}

However VLC no longer has a main window, so that doesn't work.

If I do this,

Process.GetProcessById(id).Kill();

The videos get corrupted because VLC doesn't exist gracefully.

I tried the other methods Close, Dispose, but they don't work.

It seems to me that I need to maximise these windows first before calling CloseMainWindow, or find some other way to exit them, or if there is an option in VLC to start a new file every half an hour?

标签: c# .net-core vlc
3条回答
来,给爷笑一个
2楼-- · 2019-07-26 11:19

"Kill is the only way to terminate processes that do not have graphical interfaces."

So basically, the only chance you have to make this work is to check if VLC process offers a way to control it while running in background: in this way, you could first stop the recording process and then kill the process.

I'm not aware of what functionalities it exposes, but You could do that with VLC HTTP interface or maybe check for some dbus commands?

查看更多
干净又极端
3楼-- · 2019-07-26 11:35

try invoking vlc commands using RC (Remote command) Interface. Documentation can be found here: https://wiki.videolan.org/documentation:modules/rc/ If you start vlc with the remote commands you can then send via websocked a command to stop the recording or close vlc.

Try adding to your command

--intf rc --rc-host="my-ip:my-port" --rc-quiet --rc-extend

The list of available commands are:

longhelp
+----[ Remote control commands ]
|
| add XYZ  . . . . . . . . . . . . add XYZ to playlist
| enqueue XYZ  . . . . . . . . . queue XYZ to playlist
| playlist . . . . .  show items currently in playlist
| play . . . . . . . . . . . . . . . . . . play stream
| stop . . . . . . . . . . . . . . . . . . stop stream
| next . . . . . . . . . . . . . .  next playlist item
| prev . . . . . . . . . . . .  previous playlist item
| goto . . . . . . . . . . . . . .  goto item at index
| repeat [on|off] . . . .  toggle playlist item repeat
| loop [on|off] . . . . . . . . . toggle playlist loop
| random [on|off] . . . . . . .  toggle random jumping
| clear . . . . . . . . . . . . . . clear the playlist
| status . . . . . . . . . . . current playlist status
| title [X]  . . . . . . set/get title in current item
| title_n  . . . . . . . .  next title in current item
| title_p  . . . . . .  previous title in current item
| chapter [X]  . . . . set/get chapter in current item
| chapter_n  . . . . . .  next chapter in current item
| chapter_p  . . . .  previous chapter in current item
|
| seek X . . . seek in seconds, for instance `seek 12'
| pause  . . . . . . . . . . . . . . . .  toggle pause
| fastforward  . . . . . . . .  .  set to maximum rate
| rewind  . . . . . . . . . . . .  set to minimum rate
| faster . . . . . . . . . .  faster playing of stream
| slower . . . . . . . . . .  slower playing of stream
| normal . . . . . . . . . .  normal playing of stream
| f [on|off] . . . . . . . . . . . . toggle fullscreen
| info . . . . .  information about the current stream
| stats  . . . . . . . .  show statistical information
| get_time . . seconds elapsed since stream's beginning
| is_playing . . . .  1 if a stream plays, 0 otherwise
| get_title . . . . .  the title of the current stream
| get_length . . . .  the length of the current stream
|
| volume [X] . . . . . . . . . .  set/get audio volume
| volup [X]  . . . . . . .  raise audio volume X steps
| voldown [X]  . . . . . .  lower audio volume X steps
| adev [X] . . . . . . . . . . .  set/get audio device
| achan [X]. . . . . . . . . .  set/get audio channels
| atrack [X] . . . . . . . . . . . set/get audio track
| vtrack [X] . . . . . . . . . . . set/get video track
| vratio [X]  . . . . . . . set/get video aspect ratio
| vcrop [X]  . . . . . . . . . . .  set/get video crop
| vzoom [X]  . . . . . . . . . . .  set/get video zoom
| snapshot . . . . . . . . . . . . take video snapshot
| strack [X] . . . . . . . . . set/get subtitles track
| key [hotkey name] . . . . . .  simulate hotkey press
| menu . . [on|off|up|down|left|right|select] use menu
|
| @name marq-marquee  STRING  . . overlay STRING in video
| @name marq-x X . . . . . . . . . . . .offset from left
| @name marq-y Y . . . . . . . . . . . . offset from top
| @name marq-position #. . .  .relative position control
| @name marq-color # . . . . . . . . . . font color, RGB
| @name marq-opacity # . . . . . . . . . . . . . opacity
| @name marq-timeout T. . . . . . . . . . timeout, in ms
| @name marq-size # . . . . . . . . font size, in pixels
|
| @name logo-file STRING . . .the overlay file path/name
| @name logo-x X . . . . . . . . . . . .offset from left
| @name logo-y Y . . . . . . . . . . . . offset from top
| @name logo-position #. . . . . . . . relative position
| @name logo-transparency #. . . . . . . . .transparency
|
| @name mosaic-alpha # . . . . . . . . . . . . . . alpha
| @name mosaic-height #. . . . . . . . . . . . . .height
| @name mosaic-width # . . . . . . . . . . . . . . width
| @name mosaic-xoffset # . . . .top left corner position
| @name mosaic-yoffset # . . . .top left corner position
| @name mosaic-offsets x,y(,x,y)*. . . . list of offsets
| @name mosaic-align 0..2,4..6,8..10. . .mosaic alignment
| @name mosaic-vborder # . . . . . . . . vertical border
| @name mosaic-hborder # . . . . . . . horizontal border
| @name mosaic-position {0=auto,1=fixed} . . . .position
| @name mosaic-rows #. . . . . . . . . . .number of rows
| @name mosaic-cols #. . . . . . . . . . .number of cols
| @name mosaic-order id(,id)* . . . . order of pictures
| @name mosaic-keep-aspect-ratio {0,1} . . .aspect ratio
|
| help . . . . . . . . . . . . . . . this help message
| longhelp . . . . . . . . . . . a longer help message
| logout . . . . . . .  exit (if in socket connection)
| quit . . . . . . . . . . . . . . . . . . .  quit vlc
|
+----[ end of help ]

This question is similar to yours, and this specific answer explains why CTRLC is not the right way to close: VLC screen capture using terminal.

Example usage: http://sureskumar.com/RemoteVLC/#examples (Arduino code but easy to understand)

查看更多
你好瞎i
4楼-- · 2019-07-26 11:41

Thanks Norcino, your solution works well. I added in the options you mentioned,

-I rc --rc-host=192.168.1.4:10001 --rc-quiet

Then my C# looks like this,

KillSingleInstance(10001);

public void KillSingleInstance(int port)
{
    List<byte> ip = new List<byte>();

    ip.Add(192);
    ip.Add(168);
    ip.Add(1);
    ip.Add(4);

    IPAddress ipAddress = new IPAddress(ip.ToArray());
    IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

    Socket sender = new Socket(ipAddress.AddressFamily,  
        SocketType.Stream, ProtocolType.Tcp); 

    sender.Connect(remoteEP);

    byte[] msg = Encoding.ASCII.GetBytes("quit\n"); 

    sender.Send(msg);

    sender.Shutdown(SocketShutdown.Both);  
    sender.Close();
}

The VLC instances are completely running in the background.

Plus it has a try and catch block etc. Will do more testing, but so far works well.

查看更多
登录 后发表回答