release candidate
This commit is contained in:
@ -8,7 +8,8 @@ There is a hardware requirement of USB RCA Capture device, and this device must
|
||||
|
||||
There is an option to install a basic GUI and then display the feed in a browser kiosk
|
||||
|
||||
This platform requires too much processing power to be installed on weak systems. The RK3528A 4-core SBC loads up to 6 when this runs on it. Perhaps a future version of this will have a detector so that when it's installed on a wimpy ARM SBC it will do nothing except save the file; no MediaMTX or Jellyfin. Not important right now.
|
||||
This platform requires too much processing power to be installed on even half-decent systems. An 8-core Ryzen 5 Mini-PC is incapable of running the entire stack. I have separated the implementation of this to a client and server model. I set up a new VM on my home server that can use nearly all the CPU cores when needed, and set that with a static IP. I created two new roles that call this role with a few different variables, and then the cosmos-server pipeline can be ran with a special server selected to build the default cosmos VHS capture stack. This can probably run on an Intel i9 Mini PC or a similarly beefy Ryzen. It turns out that just the A/V to RSTP job takes a non-trivial amount of compute. Trying to do that and the video encoding at the same time generally takes more than a small CPU can offer. Now there is a VCR server VM that does the capturing of both the preview stream and the capture stream. This also saves it to the network in a spot that the website can automatically see. The client just streams to the server and displays the feed that is running from the server.
|
||||
|
||||
|
||||
This process uses stages of different software to accomplish the goal of making capturing a VHS tape as automatic as possible
|
||||
|
||||
|
||||
27
defaults/kiosk.yaml
Normal file
27
defaults/kiosk.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
|
||||
|
||||
# kiosk vars
|
||||
kiosk_service_templates:
|
||||
- chrome_website: "http://{{ stream_control_host }}:8081"
|
||||
service_name: user_stream_control
|
||||
service_description: "VCR Capture User Stream Control"
|
||||
extra_service_configs: ""
|
||||
user_data_dir: "/opt/chrome/one"
|
||||
extra_chrome_configs: |
|
||||
--window-size="560,1080" \
|
||||
--user-data-dir=/opt/chrome/one \
|
||||
--device-scale-factor="200" \
|
||||
- chrome_website: "http://{{ stream_preview_host }}:8888/stream"
|
||||
service_name: stream_preview
|
||||
service_description: "VCR Capture Preview Stream"
|
||||
extra_service_configs: ""
|
||||
user_data_dir: "/opt/chrome/two"
|
||||
extra_chrome_configs: |
|
||||
--window-size="1350,1080" \
|
||||
--user-data-dir=/opt/chrome/two \
|
||||
--window-position="570,0" \
|
||||
--device-scale-factor="200" \
|
||||
|
||||
|
||||
...
|
||||
@ -1,69 +1,9 @@
|
||||
---
|
||||
|
||||
working_storage: "/media/sd_card"
|
||||
|
||||
owncast_capture_folder: "{{ working_storage }}/owncast"
|
||||
|
||||
recording_capture_folder: "{{ working_storage }}/recordings"
|
||||
|
||||
streaming_working_folder: "/opt/cosmos/streamer"
|
||||
|
||||
mediamtx_working_folder: "/opt/cosmos/mediamtx"
|
||||
|
||||
jellyfin_working_folder: "/opt/cosmos/jellyfin"
|
||||
|
||||
jellyfin_port: "8096"
|
||||
|
||||
service_control_folder: "/opt/cosmos/streamer/service_control"
|
||||
|
||||
video_device: "/dev/video0"
|
||||
|
||||
v4l2_id_string: "AV TO USB2.0"
|
||||
|
||||
audio_device: "hw:0,0"
|
||||
|
||||
mediamtx_architecture: "amd64"
|
||||
|
||||
lsusb_device_ID: "534d:0021"
|
||||
|
||||
capture_device_ID_string: "MS210"
|
||||
|
||||
service_control_name: "stream_service.service"
|
||||
|
||||
service_name: "VCR Streamer"
|
||||
|
||||
container_name: "service_control"
|
||||
|
||||
mediamtx_local_version: "deadbeef_test"
|
||||
|
||||
storage_unmounted: true
|
||||
|
||||
mount_storge: true
|
||||
|
||||
format_storage: false
|
||||
|
||||
sd_unmounted: true
|
||||
|
||||
arm_arch: false
|
||||
|
||||
refresh_special: true
|
||||
|
||||
kiosk_models:
|
||||
- "Surface Pro 2"
|
||||
|
||||
install_kodi: false
|
||||
|
||||
local_username: "cosmos"
|
||||
|
||||
chrome_website: "http://localhost:8888/stream"
|
||||
|
||||
fixed_size: "--start-fullscreen"
|
||||
|
||||
# package list
|
||||
streamer_packages:
|
||||
- gdisk
|
||||
- ffmpeg
|
||||
- alsa-utils
|
||||
# - alsa-oss
|
||||
- alsa-firmware-loaders
|
||||
- apulse
|
||||
- libasound2-plugins
|
||||
@ -72,7 +12,25 @@ streamer_packages:
|
||||
- python3-venv
|
||||
- python3-setuptools
|
||||
|
||||
# media_mtx variables
|
||||
# jenkinsfile vars
|
||||
refresh_special: false
|
||||
GUI_deploy: false
|
||||
extra_storage: false
|
||||
kiosk_refresh: false
|
||||
remote_deploy: false
|
||||
server_deploy: false
|
||||
luna_offload: false
|
||||
|
||||
# jellfin vars
|
||||
jellyfin_working_folder: "/opt/cosmos/jellyfin"
|
||||
jellyfin_port: "8096"
|
||||
jellyfin_deploy: false
|
||||
|
||||
# mediamtx vars
|
||||
mediamtx_working_folder: "/opt/cosmos/mediamtx"
|
||||
mediamtx_architecture: "amd64"
|
||||
mediamtx_local_version: "deadbeef_test"
|
||||
# config.yaml variables
|
||||
mediamtx_configs:
|
||||
- search_string: 'record:'
|
||||
line: ' record: no'
|
||||
@ -84,5 +42,74 @@ mediamtx_configs:
|
||||
line: ' recordDeleteAfter: 0s'
|
||||
- search_string: 'recordMaxPartSize'
|
||||
line: ' recordMaxPartSize: 500M'
|
||||
# luna offload vars
|
||||
mediamtx_remote_ffmpeg: ""
|
||||
mediamtx_local_ffmpeg: ""
|
||||
|
||||
# kiosk vars
|
||||
stream_preview_host: "localhost"
|
||||
stream_control_host: "localhost"
|
||||
|
||||
#kiosk_service_templates:
|
||||
# - chrome_website: "http://localhost:8081"
|
||||
# service_name: user_stream_control
|
||||
# service_description: "VCR Capture User Stream Control"
|
||||
# extra_service_configs: ""
|
||||
# user_data_dir: "/opt/chrome/one"
|
||||
# extra_chrome_configs: |
|
||||
# --window-size="560,1080" \
|
||||
# --user-data-dir=/opt/chrome/one \
|
||||
# --device-scale-factor="200" \
|
||||
# - chrome_website: "http://{{ stream_preview_host }}:8888/stream"
|
||||
# service_name: stream_preview
|
||||
# service_description: "VCR Capture Preview Stream"
|
||||
# extra_service_configs: ""
|
||||
# user_data_dir: "/opt/chrome/two"
|
||||
# extra_chrome_configs: |
|
||||
# --window-size="1350,1080" \
|
||||
# --user-data-dir=/opt/chrome/two \
|
||||
# --window-position="570,0" \
|
||||
# --device-scale-factor="200" \
|
||||
|
||||
# rtsp site vars
|
||||
rtsp_site_working_folder: "/opt/cosmos/rtsp_site"
|
||||
|
||||
# service control vars
|
||||
service_control_folder: "/opt/cosmos/streamer/service_control"
|
||||
service_control_name: "stream_service.service"
|
||||
service_name: "VCR Streamer"
|
||||
container_name: "service_control"
|
||||
|
||||
# streamer service vars
|
||||
streaming_working_folder: "/opt/cosmos/streamer"
|
||||
video_device: "/dev/video0"
|
||||
v4l2_id_string:
|
||||
- "AV TO USB2.0"
|
||||
- "USB Video"
|
||||
audio_device: "hw:0,0"
|
||||
lsusb_device_ID: "534d:0021"
|
||||
capture_device_ID_string: "MS210"
|
||||
|
||||
# preview service vars
|
||||
stream_preview_folder: "/opt/cosmos/preview"
|
||||
|
||||
# working folder vars
|
||||
working_storage: "/media/sd_card"
|
||||
recording_capture_folder: "{{ working_storage }}/recordings"
|
||||
storage_unmounted: true
|
||||
mount_storge: true
|
||||
format_storage: false
|
||||
sd_unmounted: true
|
||||
|
||||
# other vars
|
||||
arm_arch: false
|
||||
kiosk_models:
|
||||
- "Surface Pro 2"
|
||||
- "11G5S0C900"
|
||||
arm_gui_list:
|
||||
- "RK3588"
|
||||
local_username: "cosmos"
|
||||
armcpu_check: false
|
||||
MediaMTX_only: false
|
||||
arm_device_found: false
|
||||
...
|
||||
BIN
files/jellyfin-old.tar.gz
Normal file
BIN
files/jellyfin-old.tar.gz
Normal file
Binary file not shown.
Binary file not shown.
7
scratch
Normal file
7
scratch
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
ffmpeg \
|
||||
-f alsa -i {{ audio_device }} -thread_queue_size 64 \
|
||||
-f v4l2 -framerate 24 -video_size 640x480 -input_format yuyv422 -i {{ video_device }} \
|
||||
-c:v libx264 -preset fast -crf 23 -c:a aac -b:a 192k -tune zerolatency \
|
||||
-f mp4 {{ recording_capture_folder }}/$DATE.mp4
|
||||
|
||||
22
tasks/arm_gui_check.yaml
Normal file
22
tasks/arm_gui_check.yaml
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
|
||||
# need to put this little guy in a file to do a loop
|
||||
|
||||
- name: Video Capture - run product command
|
||||
shell: "lspci | grep '{{ arm_gui_list_item }}' | head -n 1 | awk {'print $8'}"
|
||||
register: prod_name_output
|
||||
|
||||
- name: Video Capture - check for output
|
||||
ignore_errors: yes
|
||||
debug:
|
||||
msg: "System Info: {{prod_name_output.stdout_lines[0] }}"
|
||||
|
||||
- name: Video Capture - Check for GUI-approved platform
|
||||
ignore_errors: yes
|
||||
set_fact:
|
||||
GUI_deploy: "{{ prod_name_output.stdout_lines[0] in kiosk_models }}"
|
||||
arm_device_found: true
|
||||
|
||||
|
||||
|
||||
...
|
||||
@ -4,6 +4,12 @@
|
||||
# Install Jellyfin
|
||||
###############################################
|
||||
|
||||
- name: jellyfin - stop and delete container if running
|
||||
ignore_errors: true
|
||||
shell: |
|
||||
docker stop jellyfin
|
||||
docker rm jellyfin
|
||||
|
||||
- name: jellyfin - create folder
|
||||
file:
|
||||
path: "{{ jellyfin_working_folder }}"
|
||||
@ -12,6 +18,7 @@
|
||||
|
||||
# Extract jellyfin configs
|
||||
- name: jellyfin - Extract jellyfin.tar.gz
|
||||
when: not refresh_special | bool
|
||||
unarchive:
|
||||
src: jellyfin.tar.gz
|
||||
dest: "/opt/cosmos"
|
||||
@ -28,10 +35,11 @@
|
||||
- name: "jellyfin - Start container at {{ jellyfin_port }}"
|
||||
shell: "docker-compose -f {{ jellyfin_working_folder }}/docker-compose.yaml up -d"
|
||||
register: jellyfin_output
|
||||
- debug:
|
||||
msg:
|
||||
- "Docker compose output:"
|
||||
- "{{ jellyfin_output.stdout_lines }}"
|
||||
- "{{ jellyfin_output.stderr_lines }}"
|
||||
|
||||
#- debug:
|
||||
# msg:
|
||||
# - "Docker compose output:"
|
||||
# - "{{ jellyfin_output.stdout_lines }}"
|
||||
# - "{{ jellyfin_output.stderr_lines }}"
|
||||
|
||||
...
|
||||
@ -1,43 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Kiosk - get Product Name
|
||||
shell: "dmidecode | grep -A3 'System Info' | grep Product | cut -d: -f2 | cut -b2-"
|
||||
register: prod_name_output
|
||||
|
||||
|
||||
- name: Kiosk - Check for approved platform
|
||||
set_fact:
|
||||
install_sddm: "{{ prod_name_output.stdout_lines[0] in kiosk_models }}"
|
||||
|
||||
|
||||
- name: Kiosk - Proceed with local kiosk install
|
||||
when: install_sddm | bool
|
||||
block:
|
||||
|
||||
# install SDDM + Plasma using Kodi role
|
||||
- name: Kiosk - Install SDDM + KDE
|
||||
include_role:
|
||||
- kodi
|
||||
|
||||
# Install Chrome
|
||||
- name: Install chrome
|
||||
block:
|
||||
- name: prereqs - Chrome - Check if installed
|
||||
command: dpkg -l google-chrome-stable
|
||||
register: chrome_installed
|
||||
ignore_errors: true
|
||||
|
||||
- name: prereqs - Chrome - Set chrome_present variable
|
||||
set_fact:
|
||||
chrome_present: "{{ chrome_installed.rc == 0 }}"
|
||||
|
||||
- name: prereqs - Install Chrome
|
||||
include_tasks: /var/jenkins_home/ansible/roles/install_apps/tasks/chrome.yaml
|
||||
when: not chrome_present | bool
|
||||
|
||||
# set up chrome kiosk using lldp_scan role
|
||||
- name: Kiosk - Install Chrome Kiosk Service
|
||||
include_role:
|
||||
- lldp_scan
|
||||
|
||||
...
|
||||
102
tasks/main.yaml
102
tasks/main.yaml
@ -1,4 +1,49 @@
|
||||
---
|
||||
|
||||
- name: Video Capture - Luna Offload Vars
|
||||
when: luna_offload | bool
|
||||
set_fact:
|
||||
mediamtx_remote_ffmpeg: "-f rtsp rtsp://172.20.20.60:8554/stream"
|
||||
stream_preview_host: "172.20.20.60"
|
||||
|
||||
- name: Video Capture - server only Vars
|
||||
when: server_deploy | bool
|
||||
set_fact:
|
||||
stream_preview_host: "172.20.20.60"
|
||||
stream_control_host: "172.20.20.60"
|
||||
|
||||
- name: Video Capture - Local stream vars
|
||||
when: remote_deploy | bool
|
||||
set_fact:
|
||||
mediamtx_local_ffmpeg: "-f rtsp rtsp://172.20.20.60:8554/stream"
|
||||
|
||||
- name: Video Capture - Remote stream vars
|
||||
when: not remote_deploy | bool
|
||||
set_fact:
|
||||
mediamtx_local_ffmpeg: "-f rtsp rtsp://localhost:8554/stream"
|
||||
|
||||
- name: Video Capture - MediaMTX Only
|
||||
when: MediaMTX_only | bool
|
||||
block:
|
||||
|
||||
- name: include mediamtx task
|
||||
include_tasks: mediamtx.yaml
|
||||
- meta: end_play
|
||||
|
||||
- name: Video Capture - Kiosk Only
|
||||
when: kiosk_refresh | bool
|
||||
block:
|
||||
|
||||
- name: display initial kiosk_service_templates
|
||||
debug:
|
||||
msg: "{{ kiosk_service_templates }}"
|
||||
|
||||
- name: Run the chrome kiosk role when it's GUI time
|
||||
include_role:
|
||||
name: chrome_kiosk
|
||||
when: GUI_deploy | bool
|
||||
- meta: end_play
|
||||
|
||||
|
||||
- name: Video Capture - Check arch if needed
|
||||
when: refresh_special | bool
|
||||
@ -12,6 +57,41 @@
|
||||
set_fact:
|
||||
cpu_architecture: "{{ cpu_architecture_output.stdout_lines[0] }}"
|
||||
|
||||
# override GUI_deploy if unauthorized
|
||||
# if non-1080p resolutions are needed
|
||||
# chrome configs can be set here on a
|
||||
# case-by-case basis
|
||||
- name: Video Capture - get Product Name for x86
|
||||
when: GUI_deploy | bool and not armcpu_check | bool
|
||||
block:
|
||||
|
||||
- name: Video Capture - run product command
|
||||
shell: "dmidecode | grep -A3 'System Info' | grep Product | cut -d: -f2 | cut -b2-"
|
||||
register: prod_name_output
|
||||
|
||||
- name: Video Capture - show output
|
||||
debug:
|
||||
msg: "System Info: {{prod_name_output.stdout_lines[0] }}"
|
||||
|
||||
- name: Video Capture - Check for GUI-approved platform
|
||||
ignore_errors: yes
|
||||
set_fact:
|
||||
GUI_deploy: "{{ prod_name_output.stdout_lines[0] in kiosk_models }}"
|
||||
|
||||
- name: Video Capture - get Product Name for arm
|
||||
when: GUI_deploy | bool and armcpu_check | bool and not arm_device_found | bool
|
||||
block:
|
||||
|
||||
- name: Video capture - arm check loop
|
||||
loop: "{{ arm_gui_list }}"
|
||||
loop_control:
|
||||
loop_var: arm_gui_list_item
|
||||
include_tasks: arm_gui_check.yaml
|
||||
|
||||
- name: Video Capture - Will we GUI?
|
||||
debug:
|
||||
msg: "GUI Deploy: {{ GUI_deploy }}"
|
||||
|
||||
- name: Video Capture - Run Once Block
|
||||
when: not refresh_special | bool
|
||||
block:
|
||||
@ -26,20 +106,28 @@
|
||||
loop_var: streamer_packages_items
|
||||
|
||||
- name: Video Capture - Working Folder Handler
|
||||
when: not remote_deploy | bool
|
||||
include_tasks: working_folder.yaml
|
||||
|
||||
- name: Video Capture - Configure MediaMTX
|
||||
when: not remote_deploy | bool
|
||||
include_tasks: mediamtx.yaml
|
||||
|
||||
- name: Video Capture - Configure Jellyfin
|
||||
when: '"amd64" in cpu_architecture'
|
||||
include_tasks: jellyfin.yaml
|
||||
|
||||
- name: Video Capture - Configure Streaming
|
||||
include_tasks: streamer.yaml
|
||||
|
||||
- name: Video Capture - Configure service control
|
||||
when: not remote_deploy | bool
|
||||
include_tasks: service_control.yaml
|
||||
|
||||
- name: Video Capture - Configure Streaming
|
||||
when: not server_deploy | bool
|
||||
include_tasks: streamer.yaml
|
||||
|
||||
- name: Video Capture - Configure Jellyfin
|
||||
when: '"amd64" in cpu_architecture and jellyfin_deploy | bool and not remote_deploy | bool'
|
||||
include_tasks: jellyfin.yaml
|
||||
|
||||
- name: Run the chrome kiosk role when it's GUI time
|
||||
include_role:
|
||||
name: chrome_kiosk
|
||||
when: GUI_deploy | bool and not server_deploy | bool
|
||||
|
||||
...
|
||||
@ -18,7 +18,7 @@
|
||||
group: root
|
||||
|
||||
- name: MediaMTX - check for arm
|
||||
when: '"arm" in cpu_architecture'
|
||||
when: armcpu_check | bool
|
||||
set_fact:
|
||||
mediamtx_architecture: "arm64"
|
||||
|
||||
|
||||
31
tasks/preview.yaml
Normal file
31
tasks/preview.yaml
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
|
||||
# this is not just for preview but for capture too
|
||||
|
||||
- name: video_capture - streamer - preview - create folder
|
||||
file:
|
||||
path: "{{ stream_preview_folder }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: video_capture - streamer - preview - copy service script
|
||||
template:
|
||||
src: preview_service.sh
|
||||
dest: "{{ stream_preview_folder }}/preview_service.sh"
|
||||
mode: 0755
|
||||
|
||||
- name: video_capture - streamer - preview - create service file
|
||||
template:
|
||||
src: preview_service.service
|
||||
dest: /etc/systemd/system/preview_service.service
|
||||
mode: 0644
|
||||
|
||||
- name: video_capture - streamer - preview - daemon reload
|
||||
systemd:
|
||||
name: preview_service.service
|
||||
state: started
|
||||
enabled: yes
|
||||
daemon_reload: yes
|
||||
|
||||
|
||||
...
|
||||
@ -151,4 +151,28 @@
|
||||
msg="{{ docker_output.stdout_lines }}"
|
||||
msg="{{ docker_output.stderr_lines }}"
|
||||
|
||||
# create streaming service
|
||||
# this used to live with the streamer but i moved it here because most of the time this will be split up
|
||||
# the names don't make as much sense anymore either...
|
||||
# oh well...
|
||||
|
||||
- name: video_capture - fil - ffmpeg service
|
||||
#when: false
|
||||
block:
|
||||
- name: video_capture - streamer - copy service script
|
||||
template:
|
||||
src: stream_service.sh
|
||||
dest: "{{ streaming_working_folder }}/stream_service.sh"
|
||||
mode: 0755
|
||||
|
||||
- name: video_capture - streamer - create service file
|
||||
template:
|
||||
src: stream_service.service
|
||||
dest: /etc/systemd/system/stream_service.service
|
||||
mode: 0644
|
||||
|
||||
- name: video_capture - streamer - daemon reload
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
|
||||
...
|
||||
|
||||
@ -10,6 +10,21 @@
|
||||
mode: '0755'
|
||||
owner: root
|
||||
group: root
|
||||
register: folder_output
|
||||
- debug:
|
||||
msg: "{{ folder_output }}"
|
||||
|
||||
# Create capture Folder
|
||||
- name: "video_capture - streamer - create {{ recording_capture_folder }} folder"
|
||||
file:
|
||||
path: "{{ recording_capture_folder }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
owner: root
|
||||
group: root
|
||||
register: folder_output_2
|
||||
- debug:
|
||||
msg: "{{ folder_output_2 }}"
|
||||
|
||||
# this service shouldn't stay running
|
||||
- name: video_capture - streamer - stop stream_service if running
|
||||
@ -35,37 +50,59 @@
|
||||
|
||||
# same with video, the lsusb ID is 534d:0021
|
||||
# v4l2-ctl shows it as "AV TO USB2.0"
|
||||
# this checks a list and saves the only correct output
|
||||
|
||||
- name: video_capture - check for each video device
|
||||
shell: "v4l2-ctl --list-devices 2> /dev/null | grep -A3 '{{ v4l2_strings }}' | grep video | head -n 1 | awk '{print $1}' || true"
|
||||
register: v4l2_id_string_check
|
||||
loop: "{{ v4l2_id_string }}"
|
||||
loop_control:
|
||||
loop_var: v4l2_strings
|
||||
|
||||
- name: video_capture - get video device
|
||||
shell: "v4l2-ctl --list-devices 2> /dev/null | grep -A3 '{{ v4l2_id_string }}' | grep video | head -n 1 | awk '{print $1}'"
|
||||
register: video_ID_0
|
||||
|
||||
- name: video_capture - set video_device
|
||||
set_fact:
|
||||
video_device: "{{ video_ID_0.stdout_lines[0] }}"
|
||||
|
||||
when: video_check_output.stdout | length > 0
|
||||
set_fact:
|
||||
video_device: "{{ video_check_output.stdout_lines[0] }}"
|
||||
no_log: true
|
||||
loop: "{{ v4l2_id_string_check.results }}"
|
||||
loop_control:
|
||||
loop_var: video_check_output
|
||||
|
||||
- name: video_capture - show results
|
||||
debug:
|
||||
msg:
|
||||
- "Audio Device: {{ audio_device }}"
|
||||
- "Video Device: {{ video_device }}"
|
||||
|
||||
- name: video_capture - streamer - copy service script
|
||||
template:
|
||||
src: stream_service.sh
|
||||
dest: "{{ streaming_working_folder }}/stream_service.sh"
|
||||
mode: 0755
|
||||
# adding the preview service here
|
||||
- name: video_capture - streamer - preview - ffmpeg service
|
||||
#when: false
|
||||
block:
|
||||
|
||||
- name: video_capture - streamer - create service file
|
||||
template:
|
||||
src: stream_service.service
|
||||
dest: /etc/systemd/system/stream_service.service
|
||||
mode: 0644
|
||||
- name: video_capture - streamer - preview - create folder
|
||||
file:
|
||||
path: "{{ stream_preview_folder }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: video_capture - streamer - daemon reload
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
- name: video_capture - streamer - preview - copy service script
|
||||
template:
|
||||
src: preview_service.sh
|
||||
dest: "{{ stream_preview_folder }}/preview_service.sh"
|
||||
mode: 0755
|
||||
|
||||
- name: video_capture - streamer - preview - create service file
|
||||
template:
|
||||
src: preview_service.service
|
||||
dest: /etc/systemd/system/preview_service.service
|
||||
mode: 0644
|
||||
|
||||
- name: video_capture - streamer - preview - daemon reload
|
||||
systemd:
|
||||
name: preview_service.service
|
||||
state: started
|
||||
enabled: yes
|
||||
daemon_reload: yes
|
||||
|
||||
|
||||
|
||||
...
|
||||
@ -6,7 +6,7 @@
|
||||
file:
|
||||
path: "{{ working_storage }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
mode: '0777'
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
@ -20,14 +20,14 @@
|
||||
storage_unmounted: false
|
||||
|
||||
- name: Storage Handler Block
|
||||
when: storage_unmounted and mount_storge | bool
|
||||
when: storage_unmounted and mount_storge and extra_storage | bool
|
||||
block:
|
||||
|
||||
# find the device, architecture dependent
|
||||
# the arm64 is intended for the friendlyelec devices
|
||||
# which only have one sd slot, but still be careful
|
||||
- name: Storage Handler - Get Storage Device arm64
|
||||
when: '"arm64" in cpu_architecture'
|
||||
when: armcpu_check | bool
|
||||
block:
|
||||
|
||||
- name: Storage Handler - get boot device
|
||||
@ -39,7 +39,7 @@
|
||||
# this will choose the first storage device that it finds that isn't the boot device
|
||||
# be careful and don't run this on an inappropriate host
|
||||
- name: Storage Handler - Get Storage Device amd64
|
||||
when: '"amd64" in cpu_architecture'
|
||||
when: not armcpu_check | bool
|
||||
block:
|
||||
|
||||
- name: Storage Handler - get boot UUID
|
||||
@ -188,7 +188,7 @@
|
||||
path: "/etc/samba/smb.conf"
|
||||
search_string: "/etc/samba/smb.conf.d/vcr_rip.conf"
|
||||
line: "include = /etc/samba/smb.conf.d/vcr_rip.conf"
|
||||
insertbefore: '[global]'
|
||||
insertafter: '### smb.conf.d configs here'
|
||||
|
||||
- name: Working Folder - restart smbd
|
||||
service:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# docker-compose.yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
local-index:
|
||||
image: apache-index
|
||||
|
||||
14
templates/docker-compose-preview.yaml
Normal file
14
templates/docker-compose-preview.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
|
||||
services:
|
||||
web:
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- "8888:80"
|
||||
volumes:
|
||||
- {{ stream_preview_folder }}/nginx.conf:/etc/nginx/nginx.conf
|
||||
- {{ stream_preview_folder }}/html:/usr/share/nginx/html
|
||||
network_mode: bridge
|
||||
restart: always
|
||||
|
||||
...
|
||||
15
templates/preview_service.service
Normal file
15
templates/preview_service.service
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=VCR Stream Preview
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
KillSignal=SIGINT
|
||||
WorkingDirectory={{ stream_preview_folder }}
|
||||
ExecStart={{ stream_preview_folder }}/preview_service.sh
|
||||
User=root
|
||||
Group=root
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
9
templates/preview_service.sh
Normal file
9
templates/preview_service.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
ffmpeg \
|
||||
-f alsa -i {{ audio_device }} -thread_queue_size 64 \
|
||||
-f v4l2 -framerate 24 -video_size 640x480 -input_format yuyv422 -i {{ video_device }} \
|
||||
-c:v libx264 -preset fast -crf 23 -c:a aac -b:a 192k -tune zerolatency \
|
||||
{{ mediamtx_local_ffmpeg }} \
|
||||
{{ mediamtx_remote_ffmpeg }} \
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
DATE=$(date +'%Y%m%d-%H%M%S')
|
||||
|
||||
ffmpeg \
|
||||
-f alsa -i {{ audio_device }} -thread_queue_size 64 \
|
||||
-f v4l2 -framerate 30 -video_size 640x480 -input_format yuyv422 -i {{ video_device }} \
|
||||
-i rtsp://localhost:8554/stream \
|
||||
-c:v libx264 -preset fast -crf 23 -c:a aac -b:a 192k -tune zerolatency \
|
||||
-f rtsp rtsp://localhost:8554/stream \
|
||||
-f mp4 {{ recording_capture_folder }}/$DATE.mp4
|
||||
-f mp4 {{ recording_capture_folder }}/$DATE.mp4 \
|
||||
|
||||
|
||||
Reference in New Issue
Block a user