1
0
Fork 0

For webcams with video/x-raw output only

experiments
Ambrose Chua 2020-01-27 22:28:28 +08:00
parent d85b57cb61
commit 3dbc68cc4c
17 changed files with 371 additions and 46 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

5
ansible/event Normal file
View File

@ -0,0 +1,5 @@
[recorders]
#pricklypear
user@10.20.0.117 room_id=test
#voctomix_sources="[ { 'name': 'audio', 'kind': 'tcp', 'volume': '1.0' }, { 'name': 'cam1', 'kind': 'v4l2', 'device': '/dev/v4l/by-id/usb-Creative_Labs_VF0470_Live__Cam_Notebook-video-index0', 'width': '640', 'height': '480', 'framerate': '30/1' }, { 'name': 'slides', 'kind': 'v4l2', 'device': '/dev/v4l/by-id/usb-VXIS_Inc_ACASIS-video-index0', 'width': '1280', 'height': '720', 'framerate': '30/1' } ]"

View File

@ -1 +0,0 @@
pricklypear

9
ansible/group_vars/all Normal file
View File

@ -0,0 +1,9 @@
---
event:
id: 2020.fossasia.org
title: FOSSASIA Summit 2020
voctomix:
version: "voctomix2"

View File

@ -0,0 +1,23 @@
---
room_id: unknown
voctocore_enabled: true
voctogui_enabled: true
voctomix_sources:
- name: audio
kind: tcp
volume: 1.0
- name: cam1
kind: v4l2
device: /dev/v4l/by-id/usb-Creative_Labs_VF0470_Live__Cam_Notebook-video-index0
width: 640
height: 480
framerate: 30/1
- name: slides
kind: v4l2
device: /dev/v4l/by-id/usb-VXIS_Inc_ACASIS-video-index0
width: 1280
height: 720
framerate: 30/1

4
ansible/recorders.yml Normal file
View File

@ -0,0 +1,4 @@
---
- hosts: recorders
roles:
- role: recorder

View File

@ -0,0 +1,14 @@
---
- name: create artwork directory
file: dest=/opt/voctomix/artwork state=directory
owner=root group=root mode=0755
- name: copy backgrounds
copy: src=../../../artwork/{{ event.id }}/{{ item }}.png
dest=/opt/voctomix/artwork/
with_items:
- side-by-side-reverse
- side-by-side
- blank

View File

@ -1 +1,7 @@
---
- name: install general packages
apt:
state: latest
name:
- git

View File

@ -3,4 +3,5 @@
- include: packages.yml
- include: voctomix.yml
- include: voctocore.yml
- include: voctogui.yml
- include: artwork.yml
#- include: voctogui.yml

View File

@ -1,21 +1,22 @@
---
- name: installed packages required to be a mixer
apt: name={{ item }} state=latest
with_items:
- gstreamer1.0-plugins-bad
- gstreamer1.0-plugins-base
- gstreamer1.0-plugins-good
- gstreamer1.0-plugins-ugly
- gstreamer1.0-alsa
- gstreamer1.0-pulseaudio
- gstreamer1.0-tools
- libgstreamer1.0-0
- python3
- python3-gi
- python3-gi-cairo
- python3-pyinotify
- python3-scipy
- python3-sdnotify
- gir1.2-gstreamer-1.0
- gir1.2-gst-plugins-base-1.0
- gir1.2-gtk-3.0
apt:
state: latest
name:
- gstreamer1.0-plugins-bad
- gstreamer1.0-plugins-base
- gstreamer1.0-plugins-good
- gstreamer1.0-plugins-ugly
- gstreamer1.0-alsa
- gstreamer1.0-pulseaudio
- gstreamer1.0-tools
- libgstreamer1.0-0
- python3
- python3-gi
- python3-gi-cairo
- python3-pyinotify
- python3-scipy
- python3-sdnotify
- gir1.2-gstreamer-1.0
- gir1.2-gst-plugins-base-1.0
- gir1.2-gtk-3.0

View File

@ -1,32 +1,28 @@
---
- name: create voctocore config
template: src="voctomix2-config/voctocore-config.ini.j2"
dest="/opt/voctomix2/voctocore-config.ini"
template: src="voctocore-config.ini.j2"
dest="/opt/voctomix/voctocore-config.ini"
mode=0644 owner=root group=root
when: voctomix_sources is defined
- name: create voctocore systemd-unit
template: src="voctomix2-systemd-units/voctomix2-voctocore.service.j2"
dest="/etc/systemd/system/voctomix2-voctocore.service"
template: src="voctocore.service.j2"
dest="/etc/systemd/system/voctomix-voctocore.service"
mode=0644 owner=root group=root
- name: reload systemd daemon
command: systemctl daemon-reload
changed_when: false
- name: enable & (re)start voctomix2-voctocore.service when in voctomix-mode
service: name=voctomix2-voctocore.service
- name: enable & (re)start voctomix-voctocore.service
service: name=voctomix-voctocore.service
enabled=yes
state=restarted
when: encodermode is defined and encodermode == 'hd-voctomix2'
when: voctocore_enabled is defined
- name: disable & stop voctomix2-voctocore.service when not in voctomix-mode
service: name=voctomix2-voctocore.service
- name: disable & stop voctomix-voctocore.service
service: name=voctomix-voctocore.service
enabled=no
state=stopped
when: encodermode is not defined or encodermode != 'hd-voctomix2'
- name: create voctomix2-status script
template: src="voctomix2-scripts/voctomix-status.j2"
dest="/usr/bin/voctomix2-status"
mode=0755 owner=root group=root
when: voctocore_enabled is not defined

View File

@ -1,27 +1,27 @@
---
- name: create voctogui config
template: src=voctomix2-config/voctogui-config.ini.j2
dest=/opt/voctomix2/voctogui-config.ini
template: src=voctogui-config.ini.j2
dest=/opt/voctomix/voctogui-config.ini
mode=0644 owner=root group=root
- name: create voctogui systemd-unit
template: src=systemd-units/voctomix2-voctogui.service.j2
dest=/etc/systemd/system/voctomix2-voctogui.service
template: src=voctogui.service.j2
dest=/etc/systemd/system/voctomix-voctogui.service
mode=0644 owner=root group=root
- name: reload systemd daemon
command: systemctl daemon-reload
changed_when: false
- name: enable & start voctogui service when in voctomix-mode
service: name=voctomix2-voctogui
- name: enable & start voctogui service
service: name=voctomix-voctogui
enabled=yes
state=started
when: encodermode is defined and encodermode == 'hd-voctomix2'
when: voctogui_enabled is defined
- name: disable & stop voctogui service when not in voctomix-mode
service: name=voctomix2-voctogui
- name: disable & stop voctogui service
service: name=voctomix-voctogui
enabled=no
state=stopped
when: encodermode is not defined or encodermode != 'hd-voctomix2'
when: voctogui_enabled is not defined

View File

@ -1,4 +1,5 @@
---
# directories & code
- name: create voctomix directories
file: dest={{ item }} state=directory

View File

@ -0,0 +1,249 @@
[mix]
videocaps=video/x-raw,format=I420,width=1920,height=1080,framerate=30/1,pixel-aspect-ratio=1/1,interlace-mode=progressive
audiocaps=audio/x-raw,format=S16LE,channels=2,layout=interleaved,rate=48000
sources={{ voctomix_sources | map(attribute = 'name') | join(',') }}
; livesources={{ (voctomix_sources | last).name }}
backgrounds=side-by-side,side-by-side-reverse
{% for source in voctomix_sources %}
{% if source.kind == "v4l2" %}
[source.{{ source.name }}]
kind=v4l2
device={{ source.device }}
width={{ source.width }}
height={{ source.height }}
framerate={{ source.framerate }}
format=YUY2
{% endif %}
{% if source.kind == "tcp" %}
[source.{{ source.name }}]
kind=tcp
volume={{ source.volume }}
{% endif %}
{% endfor %}
[source.side-by-side]
kind=img
imguri=file:///opt/voctomix/artwork/side-by-side.png
composites=fs-sbs
[source.side-by-side-reverse]
kind=img
imguri=file:///opt/voctomix/artwork/side-by-side-reverse.png
composites=|fs-sbs
[previews]
; disable if ui & server run on the same computer and can exchange uncompressed video frames
enabled=false
deinterlace=false
live=true
videocaps=video/x-raw,width=1024,height=576,framerate=30/1
{% if voctomix_vaapi is defined and voctomix_vaapi %}
# check `vainfo`!
vaapi=h264
{% endif %}
[blinder]
enabled=false
[source.blinder]
kind=img
imguri=file:///opt/voctomix/artwork/blank.png
[overlay]
path = /opt/voctomix/overlays
[mirrors]
; disable if not needed
enabled = true
[composites]
; fullscreen source A (B is full transparent)
fs.a = *
fs.b = *
fs.alpha-b = 0
fs.noswap = true
; fullscreen source A (facing picture-in-picture)
fs-pip.a = *
fs-pip.b = 0.86/0.85 0.0
fs-pip.alpha-b = 0
fs-pip.inter = true
fs-pip.mirror = true
; fullscreen source A (facing side-by-side)
fs-sbs.a = *
fs-sbs.b = 1.0/0.5 0.0
fs-sbs.alpha-b = 0
fs-sbs.inter = true
; fullscreen source A (facing side-by-side-preview)
fs-lec.a = *
fs-lec.b = 1.0 0.0
fs-lec.alpha-b = 0
fs-lec.crop-b = 0.31/0
fs-lec.inter = true
fs-lec.mirror = true
; picture-in-picture (fullscreen source A with B as small overlay)
pip.a = *
pip.b = 0.73/0.72 0.26
pip.noswap = true
pip.mirror = true
; side-by-side (source A at left and B at right side)
sbs.a = 0.008/0.25 0.49
sbs.b = 0.503/0.25 0.49
; side-by-side-preview (source A bigger and B smaller and cropped beside)
lec.a = 0.006/0.01 0.75
lec.b = 0.60/0.42 0.56
lec.crop-b = 0.31/0
lec.mirror = true
; side-by-side-preview (source A bigger and B smaller and cropped beside)
lec_43.a = -0.125/0.0 1.0
lec_43.b = 0.60/0.42 0.56
lec_43.crop-a = 0.125/0
lec_43.crop-b = 0.31/0
lec_43.mirror = true
; fullscreen source B (overlapping A)
fs-b.a = *
fs-b.b = *
fs-b.noswap = true
; fullscreen source B (facing side-by-side)
fs-b-sbs.a = 0.0/0.5 0.0
fs-b-sbs.alpha-a = 0.0
fs-b-sbs.b = *
fs-b-sbs.inter = true
; fullscreen source B (facing side-by-side-preview)
fs-b-lec.a = 0.0/1.0 0.0
fs-b-lec.b = *
fs-b-lec.inter = true
fs-b-lec.mirror = true
; one-opon-the-other (like one-opon-the-other but overlapping)
oao.a = 0.3/0.2 0.4
oao.alpha-a = 0.5
oao.b = 0.2/0.3 0.6
oao.inter = true
oao.noswap = true
[transitions]
; list of transitions each one can be freely named and is a list of composites
; which will be morphed into an animation. Interpolation will be linear with two
; composites and B-Splines for more.
; unique name = ms, from / [... /] to
fs-fs = 750, fs / fs-b
fs-pip = 750, fs-pip / pip
fs-sbs = 750, fs-sbs / sbs
fs-b-pip = 750, fs-b / pip
fs-b-sbs = 750, fs-b-sbs / sbs
fs-lec = 750, fs-lec / lec
fs-b-lec = 750, fs-b-lec / lec
fs-lec_43 = 750, fs-lec / lec_43
fs-b-lec_43 = 750, fs-b-lec / lec_43
pip-pip = 750, pip / sbs / pip
sbs-sbs = 750, sbs / oao / sbs
_sbs-sbs = 750, ^sbs / ^oao / sbs
fs-pip_ = 750, |fs-pip / |pip
fs-b-pip_ = 750, fs-b / |pip
fs-lec_ = 750, fs-lec / |lec
fs-lec_43_ = 750, fs-lec / |lec_43
fs-b-lec_ = 750, fs-b-lec / |lec
fs-b-lec_43_ = 750, fs-b-lec / |lec_43
pip-pip_ = 750, |pip / sbs / |pip
; default blending
; unique name = ms, from / [... /] to
def = 750, * / *
[toolbar.sources.a]
buttons = cam1,slides
cam1.name = cam1
cam1.key = F1
cam1.tip = Select source cam1 on channel A
slides.name = slides
slides.key = F3
slides.tip = Select source slides on channel A
[toolbar.sources.b]
buttons = cam1,slides
cam1.name = cam1
cam1.key = 1
cam1.tip = Select source cam1 on channel B
slides.name = slides
slides.key = 3
slides.tip = Select source slides on channel B
[toolbar.composites]
buttons = fs,sbs,lec
fs.name = FULL SCREEN
fs.key = F5
fs.tip = Show channel A on full screen
sbs.name = SIDE BY SIDE
sbs.key = F6
sbs.tip = Put channel A beside channel B
lec.name = LECTURE
lec.key = F7
lec.tip = Put cropped channel B beside large channel A
[toolbar.mods]
buttons = mirror,ratio
mirror.name = MIRROR
mirror.key = F9
mirror.replace = lec->|lec
mirror.tip = Horizontally mirror composite\n(e.g. when speaker moves to the other side)
ratio.name = 4:3
ratio.replace = lec->lec_43
ratio.key = F10
ratio.tip = Crop channel A to 4:3 ratio
[toolbar.mix]
buttons = retake,cut,trans
retake.name = RETAKE
retake.key = BackSpace
retake.tip = Copy output composite to preview for modification\n(output remains untouched)
cut.name = CUT
cut.key = Return
cut.tip = Hard cut preview composite to output.
cut.expand = True
trans.name = TRANS
trans.key = space
trans.tip = Use transition to cut preview composite to output
trans.expand = True
[toolbar.insert]
auto-off.name = AUTO-OFF
auto-off.key = o
auto-off.tip = automatically turn off insertion before every mix
update.name = UPDATE
update.key = u
update.tip = Update current event
insert.name = INSERT
insert.key = i
insert.tip = Show or hide current insertion

View File

@ -0,0 +1,17 @@
#MANAGED BY ANSIBLE
[Unit]
Description = voctomix core
After=network.target
Conflicts=voctocore.service
[Service]
Type = notify
WorkingDirectory = /opt/voctomix/release
ExecStart = /opt/voctomix/release/voctocore/voctocore.py --ini-file /opt/voctomix/voctocore-config.ini -vv
Restart = always
RestartSec = 1s
StartLimitInterval = 0
[Install]
WantedBy = multi-user.target