Skip to content

Instantly share code, notes, and snippets.

@knthls
Last active December 22, 2024 20:18
Show Gist options
  • Save knthls/d67f06cbb87f85c4f39ffa2ba2ef66df to your computer and use it in GitHub Desktop.
Save knthls/d67f06cbb87f85c4f39ffa2ba2ef66df to your computer and use it in GitHub Desktop.

Revisions

  1. knthls revised this gist Jan 31, 2017. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions vlc_interface.py
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    """
    Basic Idea taken from http://stackoverflow.com/a/8111621/6420372
    """

    import os
    import socket
    import subprocess
  2. knthls created this gist Jan 31, 2017.
    109 changes: 109 additions & 0 deletions vlc_interface.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,109 @@
    import os
    import socket
    import subprocess
    from select import select
    import time
    import contextlib
    import settings

    try:
    import winreg
    except ImportError:
    import _winreg as winreg


    def _get_vlc_path():
    views = [(winreg.HKEY_CURRENT_USER, 0),
    (winreg.HKEY_LOCAL_MACHINE, winreg.KEY_WOW64_64KEY),
    (winreg.HKEY_LOCAL_MACHINE, winreg.KEY_WOW64_32KEY)]
    subkey = r'Software\VideoLAN\VLC'
    access = winreg.KEY_QUERY_VALUE
    for hroot, flag in views:
    try:
    with winreg.OpenKey(hroot, subkey, 0, access | flag) as hkey:
    value, type_id = winreg.QueryValueEx(hkey, None)
    if type_id == winreg.REG_SZ:
    return value
    except WindowsError:
    pass
    raise SystemExit("Error: VLC not found.")


    def send_command(sock, cmd, get_result=False):
    try:
    cmd = (cmd + '\n').encode('ascii')
    except AttributeError:
    cmd += b'\n'
    sent = total = sock.send(cmd)
    while total < len(cmd):
    sent = sock.send(cmd[total:])
    if sent == 0:
    raise socket.error('Socket connection broken.')
    total += sent
    if get_result:
    return receive_result(sock)


    def receive_result(sock):
    data = bytearray()
    sock.setblocking(0)
    while select([sock], [], [], 1.0)[0]:
    chunk = sock.recv(1024)
    if chunk == b'':
    raise socket.error('Socket connection broken.')
    data.extend(chunk)
    sock.setblocking(1)
    return data.decode('utf-8')


    def _outfile(id_):
    return os.path.join(settings.DATA_DIR,
    'recording_{}_.mp4'.format(id_))


    def _sout_options(id_):
    """
    somehow passing them as single options doesn't work
    :param id_:
    :return:
    """
    return "--sout=#transcode{" \
    "vcodec=h264,vb=1024,fps=" + \
    str(settings.CAM_FRAME_RATE) + ",width=640" \
    "}:standard{access=file,mux=ts," \
    "dst=" + "\"{}\"".format(_outfile(id_)) + "}"


    def _stream_options():
    return ['--dshow-size={}x{}'.format(*settings.CAM_RES),
    '--dshow-adev=None',
    '--dshow-fps={}'.format(settings.CAM_FRAME_RATE),
    '--dshow-vdev=USB_Camera']


    @contextlib.contextmanager
    def vlc(address, port, id_):
    rc_host = '{0}:{1}'.format(address, port)
    vlc = subprocess.Popen([_get_vlc_path(), '-I', 'rc', '--rc-host', rc_host,
    '--rc-quiet', 'dshow://'] + _stream_options() +
    [_sout_options(id_),'--qt-start-minimized'])

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
    sock.connect((address, port))
    yield sock
    send_command(sock, 'stop')
    send_command(sock, 'quit')
    except socket.error as e:
    exit("Error: " + e.args[0])
    finally:
    sock.close()
    # give vlc some time to finish transcoding the stream?
    time.sleep(5)
    if vlc.poll() is None:
    vlc.terminate()


    if __name__ == '__main__':
    with vlc('localhost', 12345, 42) as sock:
    time.sleep(10)