From b8c97d14ed81871eef51ba7253982c45258ec538 Mon Sep 17 00:00:00 2001 From: Sacha Chua Date: Sun, 30 Oct 2022 10:06:47 -0400 Subject: Add obs role --- roles/obs/defaults/main.yml | 5 + roles/obs/logo.png | Bin 0 -> 11774 bytes roles/obs/tasks/firefox.yml | 36 ++ roles/obs/tasks/main.yml | 79 +++++ roles/obs/tasks/mpv.yml | 38 ++ roles/obs/tasks/obs-from-source.yml | 81 +++++ roles/obs/tasks/obs-setup.yml | 37 ++ roles/obs/tasks/pulse.yml | 23 ++ roles/obs/tasks/tigervnc.yml | 54 +++ roles/obs/tasks/user.yml | 25 ++ roles/obs/tasks/xorg.conf | 33 ++ roles/obs/templates/firefox-track | 3 + roles/obs/templates/i3-config | 206 +++++++++++ roles/obs/templates/mpv-track | 5 + roles/obs/templates/mpv.conf | 28 ++ roles/obs/templates/obs-track | 3 + roles/obs/templates/profile.ini | 49 +++ roles/obs/templates/pulse | 142 ++++++++ roles/obs/templates/scenes.json | 407 ++++++++++++++++++++++ roles/obs/templates/stream-desktop-with-ffmpeg.sh | 2 + roles/obs/templates/vnc-track | 1 + roles/obs/templates/xresources | 0 roles/obs/templates/xstartup | 3 + roles/obs/templates/xstartup-track | 11 + 24 files changed, 1271 insertions(+) create mode 100644 roles/obs/defaults/main.yml create mode 100644 roles/obs/logo.png create mode 100644 roles/obs/tasks/firefox.yml create mode 100644 roles/obs/tasks/main.yml create mode 100644 roles/obs/tasks/mpv.yml create mode 100644 roles/obs/tasks/obs-from-source.yml create mode 100644 roles/obs/tasks/obs-setup.yml create mode 100644 roles/obs/tasks/pulse.yml create mode 100644 roles/obs/tasks/tigervnc.yml create mode 100644 roles/obs/tasks/user.yml create mode 100644 roles/obs/tasks/xorg.conf create mode 100755 roles/obs/templates/firefox-track create mode 100644 roles/obs/templates/i3-config create mode 100755 roles/obs/templates/mpv-track create mode 100644 roles/obs/templates/mpv.conf create mode 100755 roles/obs/templates/obs-track create mode 100644 roles/obs/templates/profile.ini create mode 100755 roles/obs/templates/pulse create mode 100644 roles/obs/templates/scenes.json create mode 100755 roles/obs/templates/stream-desktop-with-ffmpeg.sh create mode 100644 roles/obs/templates/vnc-track create mode 100644 roles/obs/templates/xresources create mode 100755 roles/obs/templates/xstartup create mode 100755 roles/obs/templates/xstartup-track diff --git a/roles/obs/defaults/main.yml b/roles/obs/defaults/main.yml new file mode 100644 index 0000000..4038fa9 --- /dev/null +++ b/roles/obs/defaults/main.yml @@ -0,0 +1,5 @@ +ff_mcustom: content_type=video/webm cluster_time_limit=5100 cluster_size_limit=2M +ff_vcustom: rt cpu-used=5 threads=2 error-resilient=1 crf=30 g=120 minrate=1.5M maxrate=1.5M +ff_vbitrate: 1500 +ff_vgopsize: 120 +obs_profile_path: /home/{{ emacsconf_user }}/.config/obs-studio/basic/profiles diff --git a/roles/obs/logo.png b/roles/obs/logo.png new file mode 100644 index 0000000..cd62aac Binary files /dev/null and b/roles/obs/logo.png differ diff --git a/roles/obs/tasks/firefox.yml b/roles/obs/tasks/firefox.yml new file mode 100644 index 0000000..d96e330 --- /dev/null +++ b/roles/obs/tasks/firefox.yml @@ -0,0 +1,36 @@ +- name: Add Firefox + apt: + name: firefox-esr + when: ansible_distribution == "Debian" +- name: Add Firefox + apt: + name: firefox-esr + when: ansible_distribution == "Ubuntu" +- name: Check if Firefox profiles exist + lineinfile: + dest: "{{ emacsconf_home }}/.mozilla/firefox/profiles.ini" + line: "Name={{ emacsconf_id }}-{{ item.id }}" + check_mode: yes + register: find_profiles + failed_when: no + loop: "{{ emacsconf_tracks }}" +- name: Fail if there are missing profiles + fail: + msg: "Please use firefox -no-remote -CreateProfile {{ emacsconf_id }}-{{ item.item.id }} in an X session to create the profiles." + when: item.changed + loop: "{{ find_profiles.results }}" +- name: Create scripts for tracks + template: + src: firefox-track + dest: "{{ emacsconf_home }}/bin/{{ item.id }}/-firefox" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + mode: 0775 + loop: "{{ emacsconf_tracks }}" + + # - debug: +# var: find_profiles.results +# - name: Create profile if it doesn't exist +# shell: xinit firefox -no-remote -CreateProfile "{{ emacsconf_id }}-{{ item.item.id }}" +# when: item.changed +# loop: "{{ find_profiles.results }}" diff --git a/roles/obs/tasks/main.yml b/roles/obs/tasks/main.yml new file mode 100644 index 0000000..cb981b1 --- /dev/null +++ b/roles/obs/tasks/main.yml @@ -0,0 +1,79 @@ +- name: Load icecast vars + tags: wip + include_vars: + file: ../../stream/defaults/main.yml +- name: Add repo + apt_repository: + repo: ppa:obsproject/obs-studio + when: ansible_distribution == "Ubuntu" +- name: Add packages + apt: + name: + - xserver-xorg-video-dummy + - i3 + - socat + - ffmpeg + - pulseaudio + - jackd2 + - alsa-utils + - dbus-x11 + - obs-studio + - xserver-xorg-dev + update_cache: yes +- name: Set up user + include: user.yml +- name: Set up track bins for addition to paths + file: + path: "{{ emacsconf_home }}/bin/{{ item.id }}" + state: directory + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + loop: "{{ emacsconf_tracks }}" +- name: Copy X11 config + template: + src: xorg.conf + dest: /etc/X11/xorg.conf +- name: Set up VNC + include: tigervnc.yml + tags: vnc, wip +- name: Set up MPV and MPVC + tags: mpv + include: mpv.yml +- name: Set up OBS profiles and scenes + tags: obs-profile + include: obs-setup.yml +- name: Add FFMPEG script for streaming + template: + src: stream-desktop-with-ffmpeg.sh + dest: /home/{{ emacsconf_user }}/bin/{{ item.id }}/stream-desktop-with-ffmpeg + mode: 0775 + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + loop: "{{ emacsconf_tracks }}" +- name: Copy logo + copy: + src: logo.png + dest: "{{ emacsconf_home }}/logo.png" +# - name: Start jack +# shell: jackd -r -ddummy +# async: 2592000 +- name: Set up pulse + include: pulse.yml + tags: pulse +- name: Set up Firefox + tags: firefox + include: firefox.yml +- name: Set up I3 directory + tags: wip + file: + path: "{{ emacsconf_home }}/.config/i3" + state: directory + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" +- name: Set up I3 + tags: wip + template: + src: i3-config + dest: "{{ emacsconf_home }}/.config/i3/config" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" diff --git a/roles/obs/tasks/mpv.yml b/roles/obs/tasks/mpv.yml new file mode 100644 index 0000000..581472a --- /dev/null +++ b/roles/obs/tasks/mpv.yml @@ -0,0 +1,38 @@ +- name: add apt-key + apt_key: + url: https://non-gnu.uvt.nl/debian/uvt_key.gpg + state: present +- name: Add repo + apt_repository: + repo: deb https://non-gnu.uvt.nl/debian {{ ansible_distribution_release }} uvt +- name: Install mpv + apt: + name: mpv=0.34.1+fruit.2 +- name: Create MPV profile directory + file: + path: "{{ emacsconf_home }}/.config/mpv" + state: directory + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" +- name: Add MPV profile + template: + src: mpv.conf + dest: "{{ emacsconf_home }}/.config/mpv/mpv.conf" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" +- name: Download MPVC + git: + repo: https://github.com/lwilletts/mpvc.git + dest: /usr/src/mpvc +- name: Install MPVC + make: + chdir: /usr/src/mpvc + target: install +- name: Create mpv scripts for tracks + template: + src: mpv-track + dest: "{{ emacsconf_home }}/bin/{{ item.id }}/-mpv" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + mode: 0775 + loop: "{{ emacsconf_tracks }}" diff --git a/roles/obs/tasks/obs-from-source.yml b/roles/obs/tasks/obs-from-source.yml new file mode 100644 index 0000000..915aeb2 --- /dev/null +++ b/roles/obs/tasks/obs-from-source.yml @@ -0,0 +1,81 @@ +- name: Install packages + package: + name: + - xrdp + - xfce4 + - firefox-esr + - mpv + - ffmpeg + - cmake + - ninja-build + - pkg-config + - clang + - clang-format + - build-essential + - curl + - ccache + - libavcodec-dev + - libavdevice-dev + - libavfilter-dev + - libavformat-dev + - libavutil-dev + - libswresample-dev + - libswscale-dev + - libx264-dev + - libcurl4-openssl-dev + - libmbedtls-dev + - libgl1-mesa-dev + - libjansson-dev + - libluajit-5.1-dev + - python3-dev + - libx11-dev + - libxcb-randr0-dev + - libxcb-shm0-dev + - libxcb-xinerama0-dev + - libxcb-composite0-dev + - libxinerama-dev + - libxcb1-dev + - libx11-xcb-dev + - libxcb-xfixes0-dev + - swig + - libcmocka-dev + - libpci-dev + - libxss-dev + - libglvnd-dev + - libgles2-mesa + - libgles2-mesa-dev + - libwayland-dev + - libxkbcommon-dev + - qtbase5-dev + - qtbase5-private-dev + - libqt5svg5-dev + - qtwayland5 + - libasound2-dev + - libfontconfig-dev + - libfreetype6-dev + - libjack-jackd2-dev + - libpulse-dev + - libsndio-dev + - libspeexdsp-dev + - libudev-dev + - libv4l-dev + - libva-dev + - libvlc-dev + - libdrm-dev +- name: Install source + git: + repo: https://github.com/obsproject/obs-studio.git + dest: /usr/src/obs + recursive: true +- name: Configure + shell: sudo cmake -S . -B build -G Ninja -DENABLE_PIPEWIRE=OFF -DENABLE_AJA=0 -DENABLE_BROWSER=OFF -DENABLE_NEW_MPEGTS_OUTPUT=OFF + args: + chdir: /usr/src/obs +- name: Build + shell: sudo cmake --build build + args: + chdir: /usr/src/obs +- name: Install + shell: sudo cmake --install build + args: + chdir: /usr/src/obs diff --git a/roles/obs/tasks/obs-setup.yml b/roles/obs/tasks/obs-setup.yml new file mode 100644 index 0000000..be82a8f --- /dev/null +++ b/roles/obs/tasks/obs-setup.yml @@ -0,0 +1,37 @@ +- name: Create OBS scene directory + file: + path: "{{ emacsconf_home }}/.config/obs-studio/basic/scenes" + state: directory + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" +- name: Create profile directories + file: + path: "{{ obs_profile_path }}/{{ item.name }}" + state: directory + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + mode: 0775 + loop: "{{ emacsconf_tracks }}" +- name: Install OBS profiles + template: + src: profile.ini + dest: "{{ obs_profile_path }}/{{ item.name }}/basic.ini" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + force: no + mode: 0664 + loop: "{{ emacsconf_tracks }}" +- name: Install OBS scenes + template: + src: scenes.json + dest: "{{ emacsconf_home }}/.config/obs-studio/basic/scenes/{{ item.id }}.json" + force: no + loop: "{{ emacsconf_tracks }}" +- name: Create OBS scripts for tracks + template: + src: obs-track + dest: "{{ emacsconf_home }}/bin/{{ item.id }}/-obs" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + mode: 0775 + loop: "{{ emacsconf_tracks }}" diff --git a/roles/obs/tasks/pulse.yml b/roles/obs/tasks/pulse.yml new file mode 100644 index 0000000..1cb71c5 --- /dev/null +++ b/roles/obs/tasks/pulse.yml @@ -0,0 +1,23 @@ +- name: Create pulse directory + file: + state: directory + path: "{{ emacsconf_home }}/.config/pulse/" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" +- name: Set up pulse configuration + template: + src: pulse + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + dest: "{{ emacsconf_home }}/.config/pulse/default.pa" + mode: 0755 +- name: Change ownership + file: + state: directory + path: "{{ emacsconf_home }}/.config/pulse/" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + recurse: true +# - name: Start pulseaudio +# become_user: "{{ emacsconf_user }}" +# shell: pulseaudio --start diff --git a/roles/obs/tasks/tigervnc.yml b/roles/obs/tasks/tigervnc.yml new file mode 100644 index 0000000..539b70e --- /dev/null +++ b/roles/obs/tasks/tigervnc.yml @@ -0,0 +1,54 @@ +- name: Add packages + apt: + name: + - tigervnc-standalone-server + - tigervnc-common +- name: Create VNC dirs + file: + path: /home/{{ emacsconf_user }}/.vnc + state: directory + mode: 0755 + owner: "{{ emacsconf_user }}" +# https://github.com/sdarwin/Ansible-VNC/blob/master/tasks/main.yml +- name: Set VNC password + become: "{{ emacsconf_user }}" + shell: | + set -o pipefail + printf "{{ vnc_password }}\n{{ vnc_password }}\n\n" | vncpasswd /home/{{ emacsconf_user }}/.vnc/passwd + args: + chdir: "/home/{{ emacsconf_user }}/.vnc" + creates: "/home/{{ emacsconf_user }}/.vnc/passwd" + executable: /bin/bash +- name: Set up xstartup + template: + src: xstartup + dest: ~{{ emacsconf_user }}/.vnc/xstartup + mode: 0700 +- name: Set up xstartup for the tracks + template: + src: xstartup-track + dest: ~{{ emacsconf_user }}/.vnc/xstartup-{{ item.id }} + mode: 0700 + loop: "{{ emacsconf_tracks }}" +- name: Set up xstartup + template: + src: xresources + dest: ~{{ emacsconf_user }}/.Xresources + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + mode: 0600 +- name: Set up VNC scripts + template: + src: vnc-track + dest: "{{ emacsconf_home }}/bin/{{ item.id }}/-vnc" + mode: 0755 + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + loop: "{{ emacsconf_tracks }}" +- name: Set permissions and ownership + file: + path: "/home/{{ emacsconf_user }}/.vnc" + owner: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" + mode: "u+rwX,g-rwx,o-rwx" + recurse: t diff --git a/roles/obs/tasks/user.yml b/roles/obs/tasks/user.yml new file mode 100644 index 0000000..c1493dd --- /dev/null +++ b/roles/obs/tasks/user.yml @@ -0,0 +1,25 @@ +- name: Add group + group: + name: "{{ emacsconf_group }}" +- name: Add user + user: + name: "{{ emacsconf_user }}" + group: "{{ emacsconf_group }}" +# password: "{{ emacsconf_unix_password }}" +- name: Create SSH folder + file: + path: "/home/{{ emacsconf_user }}/.ssh" + owner: "{{ emacsconf_user }}" + state: directory + mode: 700 +- name: Set up SSH key access + template: + src: authorized_keys + dest: "/home/{{ emacsconf_user }}/.ssh/authorized_keys" + force: no +- name: Change ownership of SSH directory + file: + path: "/home/{{ emacsconf_user }}/.ssh" + recurse: true + owner: "{{ emacsconf_user }}" + mode: "u+rwX,g-rwx,o-rwx" diff --git a/roles/obs/tasks/xorg.conf b/roles/obs/tasks/xorg.conf new file mode 100644 index 0000000..1975093 --- /dev/null +++ b/roles/obs/tasks/xorg.conf @@ -0,0 +1,33 @@ +# This xorg configuration file is meant to be used +# to start a dummy X11 server. +# For details, please see: +# https://www.xpra.org/xorg.conf + +# Here we setup a Virtual Display of 1920x1080 pixels + +Section "Device" + Identifier "Configured Video Device" + Driver "dummy" + #VideoRam 4096000 + VideoRam 256000 + #VideoRam 16384 +EndSection + +Section "Monitor" + Identifier "Configured Monitor" + HorizSync 5.0 - 1000.0 + VertRefresh 5.0 - 200.0 + Modeline "1280x720_60.00" 74.48 1280 1336 1472 1664 720 721 724 746 -HSync +Vsync +EndSection + +Section "Screen" + Identifier "Default Screen" + Monitor "Configured Monitor" + Device "Configured Video Device" + DefaultDepth 24 + SubSection "Display" + Viewport 0 0 + Depth 24 + Virtual 1280 720 + EndSubSection +EndSection \ No newline at end of file diff --git a/roles/obs/templates/firefox-track b/roles/obs/templates/firefox-track new file mode 100755 index 0000000..e3110ee --- /dev/null +++ b/roles/obs/templates/firefox-track @@ -0,0 +1,3 @@ +#!/bin/bash +# {{ ansible_managed }} +firefox -P "{{ emacsconf_id }}-{{ item.id }}" $* diff --git a/roles/obs/templates/i3-config b/roles/obs/templates/i3-config new file mode 100644 index 0000000..ce22fd3 --- /dev/null +++ b/roles/obs/templates/i3-config @@ -0,0 +1,206 @@ +# i3 config file (v4) +# +# Please see https://i3wm.org/docs/userguide.html for a complete reference! +# +# This config file uses keycodes (bindsym) and was written for the QWERTY +# layout. +# +# To get a config file with the same key positions, but for your current +# layout, use the i3-config-wizard +# + +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +font pango:monospace 8 + +# This font is widely installed, provides lots of unicode glyphs, right-to-left +# text rendering and scalability on retina/hidpi displays (thanks to pango). +#font pango:DejaVu Sans Mono 8 + +# The combination of xss-lock, nm-applet and pactl is a popular choice, so +# they are included here as an example. Modify as you see fit. + +# xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the +# screen before suspend. Use loginctl lock-session to lock your screen. +exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork + +# NetworkManager is the most popular way to manage wireless networks on Linux, +# and nm-applet is a desktop environment-independent system tray GUI for it. +exec --no-startup-id nm-applet + +# Use pactl to adjust volume in PulseAudio. +set $refresh_i3status killall -SIGUSR1 i3status +bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status +bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status +bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status +bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status + +# use these keys for focus, movement, and resize directions when reaching for +# the arrows is not convenient +set $up l +set $down k +set $left j +set $right semicolon + +# use Mouse+Mod1 to drag floating windows to their wanted position +floating_modifier Mod1 + +# start a terminal +bindsym Mod1+Return exec i3-sensible-terminal + +# kill focused window +bindsym Mod1+Shift+q kill + +# start dmenu (a program launcher) +bindsym Mod1+d exec --no-startup-id dmenu_run +# A more modern dmenu replacement is rofi: +# bindsym Mod1+d exec "rofi -modi drun,run -show drun" +# There also is i3-dmenu-desktop which only displays applications shipping a +# .desktop file. It is a wrapper around dmenu, so you need that installed. +# bindsym Mod1+d exec --no-startup-id i3-dmenu-desktop + +# change focus +bindsym Mod1+$left focus left +bindsym Mod1+$down focus down +bindsym Mod1+$up focus up +bindsym Mod1+$right focus right + +# alternatively, you can use the cursor keys: +bindsym Mod1+Left focus left +bindsym Mod1+Down focus down +bindsym Mod1+Up focus up +bindsym Mod1+Right focus right + +# move focused window +bindsym Mod1+Shift+$left move left +bindsym Mod1+Shift+$down move down +bindsym Mod1+Shift+$up move up +bindsym Mod1+Shift+$right move right + +# alternatively, you can use the cursor keys: +bindsym Mod1+Shift+Left move left +bindsym Mod1+Shift+Down move down +bindsym Mod1+Shift+Up move up +bindsym Mod1+Shift+Right move right + +# split in horizontal orientation +bindsym Mod1+h split h + +# split in vertical orientation +bindsym Mod1+v split v + +# enter fullscreen mode for the focused container +bindsym Mod1+f fullscreen toggle + +# change container layout (stacked, tabbed, toggle split) +bindsym Mod1+s layout stacking +bindsym Mod1+w layout tabbed +bindsym Mod1+e layout toggle split + +# toggle tiling / floating +bindsym Mod1+Shift+space floating toggle + +# change focus between tiling / floating windows +bindsym Mod1+space focus mode_toggle + +# focus the parent container +bindsym Mod1+a focus parent + +# focus the child container +#bindsym Mod1+d focus child + +# move the currently focused window to the scratchpad +bindsym Mod1+Shift+minus move scratchpad + +# Show the next scratchpad window or hide the focused scratchpad window. +# If there are multiple scratchpad windows, this command cycles through them. +bindsym Mod1+minus scratchpad show + +# Define names for default workspaces for which we configure key bindings later on. +# We use variables to avoid repeating the names in multiple places. +set $ws1 "1" +set $ws2 "2" +set $ws3 "3" +set $ws4 "4" +set $ws5 "5" +set $ws6 "6" +set $ws7 "7" +set $ws8 "8" +set $ws9 "9" +set $ws10 "10" + +# switch to workspace +bindsym Mod1+1 workspace number $ws1 +bindsym Mod1+2 workspace number $ws2 +bindsym Mod1+3 workspace number $ws3 +bindsym Mod1+4 workspace number $ws4 +bindsym Mod1+5 workspace number $ws5 +bindsym Mod1+6 workspace number $ws6 +bindsym Mod1+7 workspace number $ws7 +bindsym Mod1+8 workspace number $ws8 +bindsym Mod1+9 workspace number $ws9 +bindsym Mod1+0 workspace number $ws10 + +# move focused container to workspace +bindsym Mod1+Shift+1 move container to workspace number $ws1 +bindsym Mod1+Shift+2 move container to workspace number $ws2 +bindsym Mod1+Shift+3 move container to workspace number $ws3 +bindsym Mod1+Shift+4 move container to workspace number $ws4 +bindsym Mod1+Shift+5 move container to workspace number $ws5 +bindsym Mod1+Shift+6 move container to workspace number $ws6 +bindsym Mod1+Shift+7 move container to workspace number $ws7 +bindsym Mod1+Shift+8 move container to workspace number $ws8 +bindsym Mod1+Shift+9 move container to workspace number $ws9 +bindsym Mod1+Shift+0 move container to workspace number $ws10 + +# reload the configuration file +bindsym Mod1+Shift+c reload +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +bindsym Mod1+Shift+r restart +# exit i3 (logs you out of your X session) +bindsym Mod1+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'" + +# resize window (you can also use the mouse for that) +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + # Pressing left will shrink the window’s width. + # Pressing right will grow the window’s width. + # Pressing up will shrink the window’s height. + # Pressing down will grow the window’s height. + bindsym $left resize shrink width 10 px or 10 ppt + bindsym $down resize grow height 10 px or 10 ppt + bindsym $up resize shrink height 10 px or 10 ppt + bindsym $right resize grow width 10 px or 10 ppt + + # same bindings, but for the arrow keys + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Down resize grow height 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt + bindsym Right resize grow width 10 px or 10 ppt + + # back to normal: Enter or Escape or Mod1+r + bindsym Return mode "default" + bindsym Escape mode "default" + bindsym Mod1+r mode "default" +} + +bindsym Mod1+r mode "resize" + +# Start i3bar to display a workspace bar (plus the system information i3status +# finds out, if available) +bar { + status_command i3status +} + +####################################################################### +# automatically start i3-config-wizard to offer the user to create a +# keysym-based config which used their favorite modifier (alt or windows) +# +# i3-config-wizard will not launch if there already is a config file +# in ~/.config/i3/config (or $XDG_CONFIG_HOME/i3/config if set) or +# ~/.i3/config. +# +# Please remove the following exec line: +####################################################################### +exec i3-config-wizard diff --git a/roles/obs/templates/mpv-track b/roles/obs/templates/mpv-track new file mode 100755 index 0000000..b34df70 --- /dev/null +++ b/roles/obs/templates/mpv-track @@ -0,0 +1,5 @@ +#!/bin/bash +# Run MPV with the output set to the right sink and with an IPC socket +# {{ ansible_managed }} + +mpv --input-ipc-server={{ emacsconf_home }}/mpv-socket-{{ emacsconf_id }}-{{ item.id }} --audio-device=pulse/{{ item.id }}-vid --profile={{ emacsconf_id }}-talks $* diff --git a/roles/obs/templates/mpv.conf b/roles/obs/templates/mpv.conf new file mode 100644 index 0000000..5c73681 --- /dev/null +++ b/roles/obs/templates/mpv.conf @@ -0,0 +1,28 @@ +# {{ ansible_managed }} +# Requires mpv >= 0.34.0 + +# Comment out the next line if you don't want this profile loaded by default. +profile={{ emacsconf_id }}-talks +# Then you can load it with `--profile={{ emacsconf_id }}-talks` + +[{{ emacsconf_id }}-talks] +# Positioning +video-zoom=-0.15 +video-pan-y=-0.055 +sub-use-margins=yes +sub-scale-by-window=yes +sub-pos=103 +sub-margin-x=150 +sub-margin-y=40 +# Style +sub-font="Clear Sans Bold" +sub-color="1/0.82/0" +sub-blur=0.2 +sub-scale=0.9 +sub-font-size=40 +sub-border-size=0 +sub-border-color=0/1 +sub-shadow-color=0/1 +sub-shadow-offset=1.2 +sub-ass-force-style=Kerning=yes +sub-ass-line-spacing=0 diff --git a/roles/obs/templates/obs-track b/roles/obs/templates/obs-track new file mode 100755 index 0000000..5763d30 --- /dev/null +++ b/roles/obs/templates/obs-track @@ -0,0 +1,3 @@ +#!/bin/bash +# {{ ansible_managed }} +obs --profile "{{ emacsconf_id }}-{{ item.id }}" --collection "{{ item.id }}" -m diff --git a/roles/obs/templates/profile.ini b/roles/obs/templates/profile.ini new file mode 100644 index 0000000..ba09dec --- /dev/null +++ b/roles/obs/templates/profile.ini @@ -0,0 +1,49 @@ +[General] +Name={{ emacsconf_id }}-{{ item.id }} + +[Video] +BaseCX={{ res_x }} +BaseCY={{ res_y }} +OutputCX={{ res_x }} +OutputCY={{ res_y }} +FPSType=1 +FPSCommon=10 +FPSInt=20 + +[SimpleOutput] +RecEncoder=x264 +RecQuality=Small + +[Output] +Mode=Advanced + +[AdvOut] +RescaleRes={{ res_x }}x{{ res_y }} +TrackIndex=1 +RecType=FFmpeg +RecRescaleRes={{ res_x }}x{{ res_y }} +RecTracks=1 +FFOutputToFile=false +FFFormat=webm +FFFormatMimeType=video/webm +FFRescaleRes={{ res_x }}x{{ res_y }} +FFVEncoderId=139 +FFVEncoder=libvpx +FFAEncoderId=86021 +FFAEncoder=libvorbis +FFAudioTrack=1 +FFAudioMixes=1 +Pre22.1Settings=true +FLVTrack=1 +FFURL=icecast://{{ icecast_emacsconf_user }}:{{ icecast_emacsconf_password }}@{{ icecast_hostname }}:{{ icecast_port }}/{{ emacsconf_id }}/{{ item.id }}.webm +FFExtension=webm +FFMCustom={{ ff_mcustom }} +FFVBitrate={{ ff_vbitrate }} +FFVGOPSize={{ ff_vgopsize }} +FFIgnoreCompat=true +FFVCustom={{ ff_vcustom }} +FFABitrate=96 +VodTrackIndex=2 + +[Twitch] +AddonChoice=3 diff --git a/roles/obs/templates/pulse b/roles/obs/templates/pulse new file mode 100755 index 0000000..cba7fc0 --- /dev/null +++ b/roles/obs/templates/pulse @@ -0,0 +1,142 @@ +#!/usr/bin/pulseaudio -nF +# +# This file is part of PulseAudio. +# +# PulseAudio is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# PulseAudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PulseAudio; if not, see . + +# This startup script is used only if PulseAudio is started per-user +# (i.e. not in system mode) + +.fail + +### Automatically restore the volume of streams and devices +load-module module-device-restore +load-module module-card-restore + +### Automatically augment property information from .desktop files +### stored in /usr/share/application +load-module module-augment-properties + +### Should be after module-*-restore but before module-*-detect +load-module module-switch-on-port-available + +### Load audio drivers statically +### (it's probably better to not load these drivers manually, but instead +### use module-udev-detect -- see below -- for doing this automatically) +#load-module module-alsa-sink +#load-module module-alsa-source device=hw:1,0 +#load-module module-oss device="/dev/dsp" sink_name=output source_name=input +#load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input +#load-module module-null-sink +#load-module module-pipe-sink + +### Automatically load driver modules depending on the hardware available +.ifexists module-udev-detect.so +load-module module-udev-detect +.else +### Use the static hardware detection module (for systems that lack udev support) +load-module module-detect +.endif + +### Automatically connect sink and source if JACK server is present +.ifexists module-jackdbus-detect.so +.nofail +load-module module-jackdbus-detect channels=2 +.fail +.endif + +### Automatically load driver modules for Bluetooth hardware +.ifexists module-bluetooth-policy.so +load-module module-bluetooth-policy +.endif + +.ifexists module-bluetooth-discover.so +load-module module-bluetooth-discover +.endif + +### Load several protocols +.ifexists module-esound-protocol-unix.so +load-module module-esound-protocol-unix +.endif +load-module module-native-protocol-unix + +### Network access (may be configured with paprefs, so leave this commented +### here if you plan to use paprefs) +#load-module module-esound-protocol-tcp +#load-module module-native-protocol-tcp +#load-module module-zeroconf-publish + +### Load the RTP receiver module (also configured via paprefs, see above) +#load-module module-rtp-recv + +### Load the RTP sender module (also configured via paprefs, see above) +#load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'" +#load-module module-rtp-send source=rtp.monitor + +### Load additional modules from GSettings. This can be configured with the paprefs tool. +### Please keep in mind that the modules configured by paprefs might conflict with manually +### loaded modules. +.ifexists module-gsettings.so +.nofail +load-module module-gsettings +.fail +.endif + + +### Automatically restore the default sink/source when changed by the user +### during runtime +### NOTE: This should be loaded as early as possible so that subsequent modules +### that look up the default sink/source get the right value +load-module module-default-device-restore + +### Make sure we always have a sink around, even if it is a null sink. +load-module module-always-sink + +### Honour intended role device property +load-module module-intended-roles + +### Automatically suspend sinks/sources that become idle for too long +load-module module-suspend-on-idle + +### If autoexit on idle is enabled we want to make sure we only quit +### when no local session needs us anymore. +.ifexists module-console-kit.so +load-module module-console-kit +.endif +.ifexists module-systemd-login.so +load-module module-systemd-login +.endif + +### Enable positioned event sounds +load-module module-position-event-sounds + +### Cork music/video streams when a phone stream is active +load-module module-role-cork + +### Modules to allow autoloading of filters (such as echo cancellation) +### on demand. module-filter-heuristics tries to determine what filters +### make sense, and module-filter-apply does the heavy-lifting of +### loading modules and rerouting streams. +load-module module-filter-heuristics +load-module module-filter-apply + +### Make some devices default +#set-default-sink output +#set-default-source input + +{% for track in emacsconf_tracks %} +load-module module-null-sink sink_name={{ track.id }}-vid sink_properties=device.description={{ track.id }}-vid +load-module module-null-sink sink_name={{ track.id }}-qa sink_properties=device.description={{ track.id }}-qa +{% endfor %} +load-module module-stream-restore restore_device=false diff --git a/roles/obs/templates/scenes.json b/roles/obs/templates/scenes.json new file mode 100644 index 0000000..5e19f16 --- /dev/null +++ b/roles/obs/templates/scenes.json @@ -0,0 +1,407 @@ +{ + "current_program_scene": "All track audio and screen", + "current_scene": "All track audio and screen", + "current_transition": "Fade", + "groups": [], + "modules": { + "auto-scene-switcher": { + "active": false, + "interval": 300, + "non_matching_scene": "", + "switch_if_not_matching": false, + "switches": [] + }, + "output-timer": { + "autoStartRecordTimer": false, + "autoStartStreamTimer": false, + "pauseRecordTimer": true, + "recordTimerHours": 0, + "recordTimerMinutes": 0, + "recordTimerSeconds": 30, + "streamTimerHours": 0, + "streamTimerMinutes": 0, + "streamTimerSeconds": 30 + }, + "scripts-tool": [] + }, + "name": "{{ item.id }}", + "preview_locked": false, + "quick_transitions": [ + { + "duration": 300, + "fade_to_black": false, + "hotkeys": [], + "id": 1, + "name": "Cut" + }, + { + "duration": 300, + "fade_to_black": false, + "hotkeys": [], + "id": 2, + "name": "Fade" + }, + { + "duration": 300, + "fade_to_black": true, + "hotkeys": [], + "id": 3, + "name": "Fade" + } + ], + "saved_projectors": [], + "scaling_enabled": false, + "scaling_level": 0, + "scaling_off_x": 0, + "scaling_off_y": 0, + "scene_order": [ + { + "name": "All track audio and screen" + }, + { + "name": "Video audio and screen" + } + ], + "sources": [ + { + "balance": 0.5, + "deinterlace_field_order": 0, + "deinterlace_mode": 0, + "enabled": true, + "flags": 0, + "hotkeys": { + "libobs.mute": [], + "libobs.push-to-mute": [], + "libobs.push-to-talk": [], + "libobs.unmute": [] + }, + "id": "pulse_output_capture", + "mixers": 255, + "monitoring_type": 0, + "muted": false, + "name": "{{ item.id }}-qa", + "prev_ver": 469762051, + "private_settings": {}, + "push-to-mute": false, + "push-to-mute-delay": 0, + "push-to-talk": false, + "push-to-talk-delay": 0, + "settings": { + "device_id": "{{ item.id }}-qa.monitor" + }, + "sync": 0, + "versioned_id": "pulse_output_capture", + "volume": 1 + }, + { + "balance": 0.5, + "deinterlace_field_order": 0, + "deinterlace_mode": 0, + "enabled": true, + "flags": 0, + "hotkeys": { + "OBSBasic.SelectScene": [], + "libobs.hide_scene_item.Screen Capture (XSHM)": [], + "libobs.hide_scene_item.{{ item.id }}-qa": [], + "libobs.hide_scene_item.{{ item.id }}-vid": [], + "libobs.show_scene_item.Screen Capture (XSHM)": [], + "libobs.show_scene_item.{{ item.id }}-qa": [], + "libobs.show_scene_item.{{ item.id }}-vid": [] + }, + "id": "scene", + "mixers": 0, + "monitoring_type": 0, + "muted": false, + "name": "All track audio and screen", + "prev_ver": 469762051, + "private_settings": {}, + "push-to-mute": false, + "push-to-mute-delay": 0, + "push-to-talk": false, + "push-to-talk-delay": 0, + "settings": { + "custom_size": false, + "id_counter": 14, + "items": [ + { + "align": 5, + "blend_method": "default", + "blend_type": "normal", + "bounds": { + "x": 0, + "y": 0 + }, + "bounds_align": 0, + "bounds_type": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, + "crop_top": 0, + "group_item_backup": false, + "hide_transition": { + "duration": 0 + }, + "id": 1, + "locked": false, + "name": "Screen Capture (XSHM)", + "pos": { + "x": 0, + "y": 0 + }, + "private_settings": {}, + "rot": 0, + "scale": { + "x": 1, + "y": 1 + }, + "scale_filter": "disable", + "show_transition": { + "duration": 0 + }, + "visible": true + }, + { + "align": 5, + "blend_method": "default", + "blend_type": "normal", + "bounds": { + "x": 0, + "y": 0 + }, + "bounds_align": 0, + "bounds_type": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, + "crop_top": 0, + "group_item_backup": false, + "hide_transition": { + "duration": 0 + }, + "id": 12, + "locked": false, + "name": "{{ item.id }}-qa", + "pos": { + "x": 0, + "y": 0 + }, + "private_settings": {}, + "rot": 0, + "scale": { + "x": 1, + "y": 1 + }, + "scale_filter": "disable", + "show_transition": { + "duration": 0 + }, + "visible": true + }, + { + "align": 5, + "blend_method": "default", + "blend_type": "normal", + "bounds": { + "x": 0, + "y": 0 + }, + "bounds_align": 0, + "bounds_type": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, + "crop_top": 0, + "group_item_backup": false, + "hide_transition": { + "duration": 0 + }, + "id": 14, + "locked": false, + "name": "{{ item.id }}-vid", + "pos": { + "x": 0, + "y": 0 + }, + "private_settings": {}, + "rot": 0, + "scale": { + "x": 1, + "y": 1 + }, + "scale_filter": "disable", + "show_transition": { + "duration": 0 + }, + "visible": true + } + ] + }, + "sync": 0, + "versioned_id": "scene", + "volume": 1 + }, + { + "balance": 0.5, + "deinterlace_field_order": 0, + "deinterlace_mode": 0, + "enabled": true, + "flags": 0, + "hotkeys": {}, + "id": "xshm_input", + "mixers": 0, + "monitoring_type": 0, + "muted": false, + "name": "Screen Capture (XSHM)", + "prev_ver": 469762051, + "private_settings": {}, + "push-to-mute": false, + "push-to-mute-delay": 0, + "push-to-talk": false, + "push-to-talk-delay": 0, + "settings": {}, + "sync": 0, + "versioned_id": "xshm_input", + "volume": 1 + }, + { + "balance": 0.5, + "deinterlace_field_order": 0, + "deinterlace_mode": 0, + "enabled": true, + "flags": 0, + "hotkeys": { + "libobs.mute": [], + "libobs.push-to-mute": [], + "libobs.push-to-talk": [], + "libobs.unmute": [] + }, + "id": "pulse_output_capture", + "mixers": 255, + "monitoring_type": 0, + "muted": false, + "name": "{{ item.id }}-vid", + "prev_ver": 469762051, + "private_settings": {}, + "push-to-mute": false, + "push-to-mute-delay": 0, + "push-to-talk": false, + "push-to-talk-delay": 0, + "settings": { + "device_id": "{{ item.id }}-vid.monitor" + }, + "sync": 0, + "versioned_id": "pulse_output_capture", + "volume": 1 + }, + { + "balance": 0.5, + "deinterlace_field_order": 0, + "deinterlace_mode": 0, + "enabled": true, + "flags": 0, + "hotkeys": { + "OBSBasic.SelectScene": [], + "libobs.hide_scene_item.Screen Capture (XSHM)": [], + "libobs.hide_scene_item.{{ item.id }}-vid": [], + "libobs.show_scene_item.Screen Capture (XSHM)": [], + "libobs.show_scene_item.{{ item.id }}-vid": [] + }, + "id": "scene", + "mixers": 0, + "monitoring_type": 0, + "muted": false, + "name": "Video audio and screen", + "prev_ver": 469762051, + "private_settings": {}, + "push-to-mute": false, + "push-to-mute-delay": 0, + "push-to-talk": false, + "push-to-talk-delay": 0, + "settings": { + "custom_size": false, + "id_counter": 5, + "items": [ + { + "align": 5, + "blend_method": "default", + "blend_type": "normal", + "bounds": { + "x": 0, + "y": 0 + }, + "bounds_align": 0, + "bounds_type": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, + "crop_top": 0, + "group_item_backup": false, + "hide_transition": { + "duration": 0 + }, + "id": 1, + "locked": false, + "name": "{{ item.id }}-vid", + "pos": { + "x": 0, + "y": 0 + }, + "private_settings": {}, + "rot": 0, + "scale": { + "x": 1, + "y": 1 + }, + "scale_filter": "disable", + "show_transition": { + "duration": 0 + }, + "visible": true + }, + { + "align": 5, + "blend_method": "default", + "blend_type": "normal", + "bounds": { + "x": 0, + "y": 0 + }, + "bounds_align": 0, + "bounds_type": 0, + "crop_bottom": 0, + "crop_left": 0, + "crop_right": 0, + "crop_top": 0, + "group_item_backup": false, + "hide_transition": { + "duration": 0 + }, + "id": 5, + "locked": false, + "name": "Screen Capture (XSHM)", + "pos": { + "x": 0, + "y": 0 + }, + "private_settings": {}, + "rot": 0, + "scale": { + "x": 1, + "y": 1 + }, + "scale_filter": "disable", + "show_transition": { + "duration": 0 + }, + "visible": true + } + ] + }, + "sync": 0, + "versioned_id": "scene", + "volume": 1 + } + ], + "transition_duration": 300, + "transitions": [] +} diff --git a/roles/obs/templates/stream-desktop-with-ffmpeg.sh b/roles/obs/templates/stream-desktop-with-ffmpeg.sh new file mode 100755 index 0000000..273505b --- /dev/null +++ b/roles/obs/templates/stream-desktop-with-ffmpeg.sh @@ -0,0 +1,2 @@ +#!/bin/bash +while true; do ffmpeg -loglevel ${LOG:0} -ar 48000 -f alsa -channels 2 -sample_rate 48000 -i default -re -video_size {{ res_x }}x{{ res_y }} -framerate 25 -f x11grab -i :0.0 -cluster_size_limit 2M -cluster_time_limit 5100 -content_type video/webm -c:v libvpx -b:v 1M -crf 30 -g 125 -deadline good -threads 4 -f webm icecast://{{ icecast_emacsconf_user }}:{{icecast_emacsconf_password }}@live0.emacsconf.org:{{ icecast_port }}/{{ emacsconf_id }}/${1:{{ item.id }}}; sleep 5; done diff --git a/roles/obs/templates/vnc-track b/roles/obs/templates/vnc-track new file mode 100644 index 0000000..b987d8b --- /dev/null +++ b/roles/obs/templates/vnc-track @@ -0,0 +1 @@ +vncserver :{{ item.vnc_id }} -geometry {{ res_x }}x{{ res_y }} -useold -xstartup {{ emacsconf_home }}/.vnc/xstartup-{{ item.id }} -desktop {{ emacsconf_id }}-{{ item.id }} \ No newline at end of file diff --git a/roles/obs/templates/xresources b/roles/obs/templates/xresources new file mode 100644 index 0000000..e69de29 diff --git a/roles/obs/templates/xstartup b/roles/obs/templates/xstartup new file mode 100755 index 0000000..bc5c70f --- /dev/null +++ b/roles/obs/templates/xstartup @@ -0,0 +1,3 @@ +#!/bin/bash +xrdb $HOME/.Xresources +exec startxfce4 \ No newline at end of file diff --git a/roles/obs/templates/xstartup-track b/roles/obs/templates/xstartup-track new file mode 100755 index 0000000..140f836 --- /dev/null +++ b/roles/obs/templates/xstartup-track @@ -0,0 +1,11 @@ +#!/bin/bash +export MPV_SOCKET={{ emacsconf_home }}/{{ item.id }}-mpv-socket +export TRACK={{ item.id }} +export PATH="/usr/local/bin:/usr/bin:/bin:{{ emacsconf_home }}/bin/{{ item.id }}" +xrdb $HOME/.Xresources +pulseaudio --start +pacmd set-default-sink {{ item.id }}-qa +firefox file://data/emacsconf/{{ emacsconf_year }}/index-{{ item.id }}.html -P "{{ emacsconf_id }}-{{ item.id }}" & +# $HOME/{{ item.id }}-obs & +# $HOME/{{ item.id }}-mpv $HOME/logo.png & +exec i3 -- cgit v1.2.3