Config - Videocapture
Table of Contents
1 Main configuration
2 Disclaimer
| Key | Value |
|---|---|
| Support | IT-Helpdesk des psychologischen Instituts, Fabrikstrasse 8, A309 |
| Telefon | 031 631 40 44 |
| helpdesk@psy.unibe.ch | |
| Öffnungszeiten | Montag bis Freitag, 09:00-12:30 und 13:30-17:00 |
| Version | 'version/version |
3 Output formats
| Description | Videocodec | Audiocodec | Multiplexer | Suffix |
|---|---|---|---|---|
| Google's opensource WebM format. | vp9enc | opusenc | webmmux | .webm |
4 Input formats
4.1 V4L2 Camera
| Name | Type | Input | Caps | Settings | Appcaps |
|---|---|---|---|---|---|
| webcam | v4l2src | {:source :device} | |||
| AUDIOOUT | pulsesrc | ||||
| precfilter | capsfilter | webcam | image/jpeg,width=800,height=448,framerate=30/1 | ||
| jpegdec | jpegdec | precfilter | |||
| vconvert | videoconvert | jpegdec | |||
| VIDEOOUT | capsfilter | vconvert | video/x-raw,format=BGRx |
4.2 RTSP Stream
| Name | Type | Input | Caps | Settings | Appcaps |
| rtsp | rtspsrc | {:latency 100} | {:source :rtsp} | ||
| rtspvidcaps | capsfilter | rtsp | application/x-rtp,media=(string)video | ||
| VIDEOOUT | decodebin | rtspvidcaps | |||
| rtspaudiocaps | capsfilter | rtsp | application/x-rtp,media=(string)audio | ||
| AUDIOOUT | decodebin | rtspaudiocaps |
5 Global configurations
5.1 Pipelines
5.1.1 Table conversion code
This code converts the pipeline tables into EDN readable by the program at startup.
The table has to be given in the variable nodes and has to be of this format:
| Name | Type | Input | Caps | Settings | Appcaps |
|---|---|---|---|---|---|
| vcapsfilter | capsfilter | vconvert | video/x-raw, format=BGRx | {:emit-signals true} | {:media "video/x-raw" :padname "sink0"} |
| test | test | vcapsfilter | asdf |
Use this code block as <<table-to-pipeline-config(nodes=put-table-name-here)>>.
(require '[clojure.string :as str])
(defn assoc-if-exists [m k v & [read?]]
(if-not ((resolve 'str/blank?) v)
(if read?
(assoc m k (read-string v))
(assoc m k v))
m))
(reduce
#(conj %1 (-> {:name (nth %2 0) :type (nth %2 1)}
(assoc-if-exists :input (nth %2 2))
(assoc-if-exists :caps (nth %2 3))
(assoc-if-exists :settings (nth %2 4) true)
(assoc-if-exists :appcap (nth %2 5) true)))
[] nodes)
5.1.2 Video playback
| Name | Type | Input | Caps | Settings | Appcaps |
|---|---|---|---|---|---|
| filein | uridecodebin | ||||
| vconvert | videoconvert | filein | |||
| vcapsfilter | capsfilter | vconvert | video/x-raw, format=BGRx, framerate=30/1 | ||
| displaysink | appsink | vcapsfilter | {:emit-signals true} | {:device :display} | |
| aconvert | audioconvert | filein | |||
| acapsfilter | capsfilter | aconvert | audio/x-raw | ||
| audiosink | autoaudiosink | acapsfilter |
5.2 GUI States
5.2.1 Table conversion code
This code converts the GUI state tables into EDN readable by the program at startup.
The table has to be given in the variable states and has to be of this format:
| Identifier | Method | Play | Record | Stop | Init |
|---|---|---|---|---|---|
| #record-button | setDisable | true | true | false | false |
| #stop-button | setOpacity | 0.0 | 0.5 | 1.0 |
The code user may add more state columns as needed.
Use this code block as <<table-to-gui-states(states=put-table-name-here)>>.
(require '[clojure.string :as str])
(def blank? (resolve 'str/blank?))
(def lower-case (resolve 'str/lower-case))
(defn construct-states
([head-map state-map]
(let [states (keys state-map)]
(reduce #(assoc %1 (keyword (lower-case (name %2)))
(construct-states (:Identifier head-map) (:Method head-map) (get state-map %2) []))
{} states)))
([identifiers methods values state]
(if (empty? identifiers)
state
(recur (rest identifiers) (rest methods) (rest values)
(conj state {:identifier (first identifiers)
:method (first methods)
:value (first values)})))))
(defn fix-values
([states]
(reduce #(assoc %1 %2 (fix-values (get states %2) []))
{} (keys states)))
([[input & inputs] output]
(cond (nil? input) output
(number? (:value input)) (recur inputs (conj output input))
(= "true" (:value input)) (recur inputs (conj output (assoc input :value true)))
(= "false" (:value input)) (recur inputs (conj output (assoc input :value false)))
(= "nil" (:value input)) (recur inputs (conj output (assoc input :value nil)))
(blank? (:value input)) (recur inputs output)
:else (recur inputs (conj output input)))))
(let [header (first states)
body (rest states)
smap (apply assoc {} (interleave (map keyword header)
(partition (count body) (apply interleave body))))
head-map {:Identifier (:Identifier smap) :Method (:Method smap)}
state-map (dissoc smap :Identifier :Method)]
(-> (construct-states head-map state-map)
fix-values))
5.3 Configuration
5.3.1 Table conversion code
| Key | Value |
|---|---|
| :exit-action | :shutdown |
(require '[clojure.string :as str])
(reduce
#(assoc %1 (read-string (nth %2 0)) (read-string (nth %2 1)))
{} tbl)
6 Project-specific configurations
6.1 WISC
6.1.1 Format
WebM
6.1.2 Recording pipeline
| Name | Type | Input | Caps | Settings | Appcaps |
|---|---|---|---|---|---|
| webcam | v4l2src | {:source :device} | |||
| camaudio | pulsesrc | ||||
| precfilter | capsfilter | webcam | image/jpeg,width=800,height=448,framerate=30/1 | ||
| jpegdec | jpegdec | precfilter | |||
| vconvert | videoconvert | jpegdec | |||
| capsfilter | capsfilter | vconvert | video/x-raw,format=BGRx | ||
| tee1 | tee | capsfilter | |||
| videosink-queue | queue | tee1 | |||
| displaysink | appsink | videosink-queue | {:emit-signals true :drop true} | {:device :display} | |
| store-queue | queue | tee1 | |||
| video-store-valve | valve | store-queue | {:drop true} | {:storage-valve true} | |
| store-videoconvert | videoconvert | video-store-valve | |||
| store-video | vp9enc | store-videoconvert | {:deadline 1 :cpu-used 6 :cq-level 32} | {:encoder true} | |
| audio-queue | queue | camaudio | |||
| audio-store-valve | valve | audio-queue | {:drop true} | {:storage-valve true} | |
| audioconverter | audioconvert | audio-store-valve | |||
| store-audio | opusenc | audioconverter | {:encoder true} | ||
| store-container | webmmux | store-video store-audio | {:encoder true :endpoint true} |
6.1.3 GUI States
| Identifier | Method | Play | Record | Stop | Init |
|---|---|---|---|---|---|
| recordButton | setDisable | true | true | false | false |
| stopButton | setDisable | false | false | true | true |
| playButton | setDisable | true | true | false | true |
| uploadButton | setDisable | true | true | false | true |
| saveButton | setDisable | true | true | false | true |
| nukeButton | setDisable | true | true | false | false |
| offButton | setDisable | false | true | false | false |
| videoCorrectBox | setDisable | true | true | false | false |
| seekSlider | setDisable | false | true | true | true |
| videoView | setImage | nil | nil | nil | |
| videoOverlayText | setStyle | "-fx-text-fill: #0F0" | "-fx-text-fill: #F00" | ||
| videoOverlayText | setText | "Wiedergabe" | "Vorschau" | ||
| videoOverlayText | setOpacity | 0.8 | 0.0 | 0.0 | 0.8 |
6.1.4 Configuration
| Key | Value |
|---|---|
| :exit-action | :shutdown |
6.2 Praxisstelle PTP
6.2.1 Format
WebM
6.2.2 Recording pipeline
| Name | Type | Input | Caps | Settings | Appcaps |
|---|---|---|---|---|---|
| rtsp | rtspsrc | {:latency 200} | {:source :rtsp} | ||
| rtspdecode | decodebin | rtsp | |||
| audioqueue | queue | rtspdecode | {:media "audio/x-raw"} | ||
| videoqueue | queue | rtspdecode | {:media "video/x-raw"} | ||
| preconvert | videoconvert | videoqueue | |||
| videorate | videorate | preconvert | |||
| prefilter | capsfilter | videorate | video/x-raw, format=BGRx, framerate=30/1 | ||
| tee1 | tee | prefilter | |||
| displayqueue | queue | tee1 | |||
| displaysink | appsink | displayqueue | {:emit-signals true :drop true} | {:device :display} | |
| store-queue | queue | tee1 | |||
| video-store-valve | valve | store-queue | {:drop true} | {:storage-valve true} | |
| store-video-convert | videoconvert | video-store-valve | |||
| store-video-encode | vp9enc | store-video-convert | {:deadline 1 :cpu-used 8 :cq-level 32} | {:encoder true} | |
| audio-store-valve | valve | audioqueue | {:drop true} | {:storage-valve true} | |
| store-audio-convert | audioconvert | audio-store-valve | |||
| store-audio-encode | opusenc | store-audio-convert | {:encoder true} | ||
| store-container | webmmux | store-video-encode store-audio-encode | {:encoder true :endpoint true} |
6.2.3 GUI States
| Identifier | Method | Play | Record | Stop | Init | Disable-supervisor |
|---|---|---|---|---|---|---|
| recordButton | setDisable | true | true | false | false | |
| stopButton | setDisable | false | false | true | true | |
| playButton | setDisable | true | true | false | true | |
| saveButton | setDisable | true | true | false | true | |
| nukeButton | setDisable | true | true | false | false | |
| offButton | setDisable | false | true | false | false | |
| videoCorrectBox | setDisable | true | true | false | false | |
| seekSlider | setDisable | false | true | true | true | |
| videoView | setImage | nil | nil | nil | ||
| videoOverlayText | setStyle | "-fx-text-fill: #0F0" | "-fx-text-fill: #F00" | |||
| videoOverlayText | setText | "Wiedergabe" | "Vorschau" | |||
| videoOverlayText | setOpacity | 0.8 | 0.0 | 0.0 | 0.8 | |
| sourceSelectBox | setVisible | false | ||||
| supervisorTextInput | setVisible | false |
6.2.4 Configuration
| Key | Value |
|---|---|
| :exit-action | :logout |
6.3 PTP Zwei Kameras
6.3.1 Format
WebM
6.3.2 Recording pipeline
| Name | Type | Input | Caps | Settings | Appcaps |
|---|---|---|---|---|---|
| rtsp1 | rtspsrc | {:latency 200} | {:source :rtsp} | ||
| rtspvidcaps1 | capsfilter | rtsp1 | application/x-rtp,media=(string)video | ||
| rtspdecode1 | decodebin | rtspvidcaps1 | |||
| videocrop1 | videocrop | rtspdecode1 | {:media "video/x-raw" :padname "sink0"} | ||
| camaudio1 | pulsesrc | ||||
| audioqueue1 | queue | camaudio1 | {:media "audio/x-raw"} | ||
| rtsp2 | rtspsrc | {:latency 200} | {:source :rtsp} | ||
| rtspvidcaps2 | capsfilter | rtsp2 | application/x-rtp,media=(string)video | ||
| rtspdecode2 | decodebin | rtspvidcaps2 | |||
| videocrop2 | videocrop | rtspdecode2 | {:left 640} | {:media "video/x-raw" :padname "sink1"} | |
| mix | compositor | videocrop2 videocrop1 | {:sink1/xpos 641 :sink0/zorder 0} | ||
| compcaps | capsfilter | mix | video/x-raw,format=BGRx,framerate=30/1,width=1280,height=720 | ||
| tee1 | tee | compcaps | |||
| displayqueue | queue | tee1 | |||
| displaysink | appsink | displayqueue | {:emit-signals true :drop true} | {:device :display} | |
| store-queue | queue | tee1 | |||
| video-store-valve | valve | store-queue | {:drop true} | {:storage-valve true} | |
| audio-store-valve | valve | audioqueue1 | {:drop true} | {:storage-valve true} | |
| store-video-convert | videoconvert | video-store-valve | |||
| store-video-encode | vp9enc | store-video-convert | {:deadline 1 :cpu-used 8 :cq-level 32} | {:encoder true} | |
| store-audio-convert | audioconvert | audio-store-valve | |||
| store-audio-encode | opusenc | store-audio-convert | {:encoder true} | ||
| store-container | webmmux | store-video-encode store-audio-encode | {:encoder true :endpoint true} |
6.3.3 GUI States
| Identifier | Method | Play | Record | Stop | Init | Disable-supervisor |
|---|---|---|---|---|---|---|
| recordButton | setDisable | true | true | false | false | |
| stopButton | setDisable | false | false | true | true | |
| playButton | setDisable | true | true | false | true | |
| saveButton | setDisable | true | true | false | true | |
| nukeButton | setDisable | true | true | false | false | |
| offButton | setDisable | false | true | false | false | |
| videoCorrectBox | setDisable | true | true | false | false | |
| seekSlider | setDisable | false | true | true | true | |
| videoView | setImage | nil | nil | nil | ||
| videoOverlayText | setStyle | "-fx-text-fill: #0F0" | "-fx-text-fill: #F00" | |||
| videoOverlayText | setText | "Wiedergabe" | "Vorschau" | |||
| videoOverlayText | setOpacity | 0.8 | 0.0 | 0.0 | 0.8 | |
| sourceSelectBox | setVisible | false | ||||
| supervisorTextInput | setVisible | false |
6.3.4 Configuration
| Key | Value |
|---|---|
| :exit-action | :logout |
7 The configuration file
{:disclaimer <<disclaimer()>>
:configs {:wisc {:file-extension ".webm"
:pipelines {:recording
<<table-to-pipeline-config(nodes=wisc-recording-pipeline-table)>>
:playback
<<table-to-pipeline-config(nodes=global-playback-pipeline-table)>>
}
:gui-states
<<table-to-gui-states(states=wisc-gui-state-table)>>
:configuration
<<table-to-config-config(tbl=wisc-config-table)>>}
:ptp {:file-extension ".webm"
:pipelines {:recording
<<table-to-pipeline-config(nodes=ptp-recording-pipeline-table)>>
:playback
<<table-to-pipeline-config(nodes=global-playback-pipeline-table)>>
}
:gui-states
<<table-to-gui-states(states=ptp-gui-state-table)>>
:configuration
<<table-to-config-config(tbl=ptp-config-table)>>}
:ptp2 {:file-extension ".webm"
:pipelines {:recording
<<table-to-pipeline-config(nodes=ptp2-recording-pipeline-table)>>
:playback
<<table-to-pipeline-config(nodes=global-playback-pipeline-table)>>
}
:gui-states
<<table-to-gui-states(states=ptp-gui-state-table)>>
:configuration
<<table-to-config-config(tbl=ptp2-config-table)>>}}
:test2
<<table-to-pipeline-config(nodes=global-playback-pipeline-table)>>}