aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorNewoIsTaken2021-08-05 14:50:02 -0400
committerNewoIsTaken2021-08-05 14:50:02 -0400
commit90c734499633586a7422d34536fc1d5cea5c0c7a (patch)
tree922e3765f5dc068b137140068a6991838ed05e9f
downloadaur-90c734499633586a7422d34536fc1d5cea5c0c7a.tar.gz
Initial commit (from jschmid1/gopro_as_webcam_on_linux with my changes)
-rw-r--r--.SRCINFO22
-rw-r--r--.gitignore5
-rw-r--r--60-gopro.rules3
-rw-r--r--PKGBUILD23
-rw-r--r--README.md166
-rwxr-xr-xgopro434
-rw-r--r--gopro-webcam.install32
-rw-r--r--gopro_webcam.service12
-rwxr-xr-xinstall.sh30
-rw-r--r--prepare_webcam.sh175
10 files changed, 902 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..6eb8fece29f3
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,22 @@
+pkgbase = gopro-webcam
+ pkgdesc = Utility to use a GoPro as a webcam
+ pkgver = 0.0.3
+ pkgrel = 1
+ url = https://github.com/NewoIsTaken/gopro_as_webcam_on_linux
+ install = gopro-webcam.install
+ arch = any
+ license = unknown
+ depends = v4l2loopback-dkms
+ depends = ffmpeg
+ optdepends = vlc: preview support
+ noextract = gopro
+ noextract = gopro_webcam.service
+ noextract = 60-gopro.rules
+ source = gopro
+ source = gopro_webcam.service
+ source = 60-gopro.rules
+ sha256sums = e1a2b49da464a1c29ac4d339e6d2d32a930b652439f442b414d4912b906c8d66
+ sha256sums = 11352f6a616bed219ee143c65cb5071545638fe1b39e616a15ff698eccab17c4
+ sha256sums = 1b3b896dd0bfaea7987dc03cfc5febcfeea77f0d48619fb3910fa002beb46f02
+
+pkgname = gopro-webcam
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000000..55b3e8af87f9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.vscode/
+*workspace
+src/
+pkg/
+*.pkg.tar.zst \ No newline at end of file
diff --git a/60-gopro.rules b/60-gopro.rules
new file mode 100644
index 000000000000..179a5639ce18
--- /dev/null
+++ b/60-gopro.rules
@@ -0,0 +1,3 @@
+SUBSYSTEM=="net", ATTRS{idVendor}=="2672", ATTRS{product}=="HERO8 BLACK", ACTION=="add", RUN+="/usr/sbin/service gopro_webcam start"
+SUBSYSTEM=="net", ATTRS{idVendor}=="2672", ATTRS{product}=="HERO8 BLACK", ACTION=="remove", RUN+="/usr/sbin/service gopro_webcam stop"
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..cbd0d59fd417
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,23 @@
+# Maintainer: Owen Wang <owenwang2007@icloud.com>
+# Maintainer: Joshua Schmid <jxs@posteo.de>
+pkgname=gopro-webcam
+pkgver=0.0.3
+pkgrel=1
+pkgdesc="Utility to use a GoPro as a webcam"
+arch=("any")
+url="https://github.com/NewoIsTaken/gopro_as_webcam_on_linux"
+license=("unknown")
+depends=("v4l2loopback-dkms" "ffmpeg")
+optdepends=("vlc: preview support")
+install=gopro-webcam.install
+source=("gopro" "gopro_webcam.service" "60-gopro.rules")
+noextract=("gopro" "gopro_webcam.service" "60-gopro.rules")
+sha256sums=("e1a2b49da464a1c29ac4d339e6d2d32a930b652439f442b414d4912b906c8d66"
+ "11352f6a616bed219ee143c65cb5071545638fe1b39e616a15ff698eccab17c4"
+ "1b3b896dd0bfaea7987dc03cfc5febcfeea77f0d48619fb3910fa002beb46f02")
+
+package() {
+ install -D gopro $pkgdir/usr/bin/gopro
+ install -D gopro_webcam.service $pkgdir/usr/lib/systemd/system/gopro_webcam.service
+ install -D 60-gopro.rules $pkgdir/lib/udev/rules.d/60-gopro.rules
+}
diff --git a/README.md b/README.md
new file mode 100644
index 000000000000..d241c67a1747
--- /dev/null
+++ b/README.md
@@ -0,0 +1,166 @@
+# Use your GoPro as a webcam on Linux (without additional hardware)
+> Currently there is no official support for using your GoPro 8&9 (the only versions that offer this feature natively) as a webcam on Linux. The web is full of incomplete tutorials for this topic. This script tries to simplify this effort.
+
+* Please note that this was only tested with the GoPro 8 on Ubuntu 20.04.
+## Installation
+
+```sh
+sudo su -c "bash <(wget -qO- https://cutt.ly/PjNkrzq)" root
+```
+
+This runs an install script. Follow the instructions on the screen.
+
+_The script install the `gopro` script to `/usr/local/sbin/gopro` and set an executable flag._
+
+See **Usage** fom here on.
+
+
+#### DEPRECATED
+
+This was the first version of the script which I'll keep around for backwards-compatibility.
+It will however not be maintained for too long.
+
+```sh
+sudo su -c "bash <(wget -qO- https://bit.ly/35wtnTl)" root
+```
+
+## Usage
+
+``` sh
+sudo gopro webcam
+```
+
+Starts the tool in the interactive mode and tries to identify the GoPro's device, find the interface and ultimately start the webcam mode.
+
+There are a couple of parameters you can set if this isn't enough. See **Synopsis** or the `--help` text
+
+
+## Synopsis
+
+```
+Usage: action [options...]
+Options:
+ -n, --non-interactive do not wait for user input. Use this when used in a startup-script/fstab
+
+ -p, --device-pattern provide a device pattern i.e. (enx, lsr) in case the script failed
+ to detect one by itself.
+
+ -d, --device provide a full device name i.e. (enxenx9245589250e7)
+ USE WITH CAUTION. THIS CHANGES EVERY TIME YOU REBOOT/RECONNECT THE CAMERA
+ THIS OPTION IS NOT SUITABLE FOR AUTOMATION!
+
+ -r, --resolution select the resolution you would like the GoPro to output. "1080", "720", or "480."
+
+ -f, --fov select the FOV you would like to use. "wide", "linear", or "narrow."
+
+ -i, --ip provide a IPv4 address to the GoPro i.e. (172.27.187.52)
+ CAUTION! This may change over time.
+
+ -a, --auto-start automatically start ffmpeg to serve the GoPro as a video device to your operating system.
+ If this flag is omitted, print the corresponding command to run it yourself.
+
+ -v, --preview Just launch a preview in VLC. This will not expose the device to the OS.
+
+ -u, --user VLC can't be started as root, please provide a username you want to run it with. (Typically your 'default/home' user)
+
+ -V, --verbose echo every command that gets executed
+
+ -h, --help display this help
+Commands:
+ webcam start the GoPro in webcam mode
+
+```
+
+## Examples
+
+`gopro webcam -p enx -n -a`
+
+Find a device that matches the pattern 'enx' (which is the gopro device for me) and starts the webcam mode without asking for user input. It also starts `ffmpeg` and exposes the device to the OS.
+
+`gopro webcam -d enxenx9245589250e7 -n -r`
+
+Use the provided device 'enxenx9245589250e7' and do not ask for user input. Just start VLC to preview the output you'll get from the Camera.
+
+
+`gopro webcam -i 172.27.187.52 -a -n`
+
+Use the provided ip '172.27.187.52' and automatically start an ffmpeg to expose the device to the OS. Also don't ask for user input.
+
+
+## Start on boot
+
+It's rather annoying to start this script every time you start up your PC. This is why I provided an example `service` file in this repository.
+
+**Note that the GoPro needs to be plugged in and be in 'standby' mode (Charger symbol) when the computer boots**
+
+
+```
+[Unit]
+Description=GoPro Webcam start script
+After=network-online.target
+Wants=network-online.target systemd-networkd-wait-online.service
+
+[Service]
+ExecStart=/usr/local/sbin/gopro webcam -p enx -a -n
+Restart=on-failure
+RestartSec=15s
+
+[Install]
+WantedBy=multi-user.target
+```
+
+Feel free to adapt it to your needs and copy it to `/etc/systemd/system/`
+
+`sudo cp gopro_webcam.service /etc/systemd/system/`
+
+`sudo systemctl start gopro_webcam.service`
+`sudo systemctl status gopro_webcam.service`
+
+Logs can be followed with `sudo journalctl -u gopro_webcam -f`
+
+If all looks fine.
+
+`sudo systemctl enable gopro_webcam.service`
+
+## Start on plug in
+
+You can also start the script when plugging in the usb cable or powering on the camera using udev rules. The script is also stopped without error when unplugging or powering off the camera. You can find an example file `60-gopro.rules` in the repo.
+
+To set this up, first follow the service installation in *Start on boot* above. You can skip the last step `sudo systemctl enable gopro_webcam.service` if you don't want to script to start and fail on every startup.
+
+Then copy the rule file `sudo cp 60-gopro.rules /lib/udev/rules.d/`. Now the setup is complete.
+
+You can check the status using `systemctl` and `journalctl` as described above.
+
+A known issue is that the first service start fails. The second service start then succeeds about 10s later. This is because even the service is only started after the ethernet interface, the network is not fully initialized. The service fails then because no ip is yet available. In the second try, the network is then usually initialized.
+
+Also the udev rule currently only works for HERO8 BLACK. The rules in the file can be duplicated and adapted for every new model supporting webcam mode released by GoPro in the future.
+
+## Dependencies
+
+```sh
+sudo apt install ffmpeg v4l2loopback-dkms
+```
+
+If your distribution doesn't provide `v4l2loopback-dkms` you may get it from https://github.com/umlaeute/v4l2loopback
+
+
+## Release History
+
+* 0.0.1
+ * Work in progress
+* 0.0.2
+ * Added args and arg parsing which
+ * Allows to run at OS startup for easily
+
+## Credits
+
+Credits go to https://github.com/KonradIT for a comprehensive documentation and tooling around inofficial GoPro things.
+
+## Contributing
+
+1. Fork it (<https://github.com/jschmid1/gopro_as_webcam_on_linux/fork>)
+2. Create your feature branch (`git checkout -b feature/fooBar`)
+3. Commit your changes (`git commit -am 'Add some fooBar'`)
+4. Push to the branch (`git push origin feature/fooBar`)
+5. Create a new Pull Request
diff --git a/gopro b/gopro
new file mode 100755
index 000000000000..becdab20b054
--- /dev/null
+++ b/gopro
@@ -0,0 +1,434 @@
+#!/usr/bin/env bash
+
+
+###################################################################
+#Author :Joshua Schmid
+#Email :jxs@posteo.de
+###################################################################
+
+VERSION=0.0.3
+
+red() {
+ echo -e "\e[31m${1}\e[0m"
+}
+
+green() {
+ echo -e "\e[32m${1}\e[0m"
+}
+
+yellow() {
+ echo -e "\e[33m${1}\e[0m"
+}
+
+function permission_check {
+ if [ "$EUID" -ne 0 ]; then
+ # the script needs root/sudo
+ red "Please run as root or with sudo"
+ exit 1
+ fi
+}
+
+globals() {
+ # TODO: Use GOPRO_ prefix
+ # TODO: rename AUTO -> NONINTERACTIVE
+ GOPRO_NON_INTERACTIVE=${GOPRO_NON_INTERACTIVE:-0}
+ GOPRO_AUTOSTART=${GOPRO_AUTOSTART:-0}
+ GOPRO_PREVIEW=${GOPRO_PREVIEW:-0}
+ GOPRO_RESOLUTION=${GOPRO_RESOLUTION:-1080}
+ GOPRO_FOV_ID=${GOPRO_FOV_ID:-4}
+ GOPRO_FOV=${GOPRO_FOV:-linear}
+ GOPRO_DEVICE_PATTERN=${GOPRO_DEVICE_PATTERN}
+ GOPRO_DEVICE=${GOPRO_DEVICE}
+ GOPRO_IP=${GOPRO_IP}
+ GOPRO_USER=${GOPRO_USER}
+}
+
+DEPS=( "ffmpeg" "curl" )
+module="v4l2loopback"
+module_cmd="modprobe v4l2loopback exclusive_caps=1 card_label='GoPro' video_nr=42"
+module_cmd_unload="modprobe -rf v4l2loopback"
+
+START_PATH="/gp/gpWebcam/START?res="
+# TODO: seems buggy atm, though
+STOP_PATH="/gp/gpWebcam/STOP"
+FOV_PATH="/gp/gpWebcam/SETTINGS?fov="
+
+function run_args {
+
+ >&2 green "Running GoPro Webcam Util for Linux [${VERSION}]"
+ >&2 echo ""
+ >&2 echo " Launch Options "
+ >&2 echo "=========================="
+ >&2 echo " * Non-interactive: $GOPRO_NON_INTERACTIVE"
+ >&2 echo " * Autostart: $GOPRO_AUTOSTART"
+ >&2 echo " * Preview: $GOPRO_PREVIEW"
+ >&2 echo " * Resolution: ${GOPRO_RESOLUTION}p"
+ >&2 echo " * FOV: $GOPRO_FOV"
+ if [[ $GOPRO_DEVICE ]]; then
+ >&2 echo " * Device: $GOPRO_DEVICE"
+ fi
+ if [[ $GOPRO_DEVICE_PATTERN ]]; then
+ >&2 echo " * Device Pattern: $GOPRO_DEVICE_PATTERN"
+ fi
+ if [[ $GOPRO_IP ]]; then
+ >&2 echo " * IP Address: $GOPRO_IP"
+ fi
+ if [[ $GOPRO_USER ]]; then
+ >&2 echo " * User: $GOPRO_USER"
+ fi
+ >&2 echo "=========================="
+ >&2 echo ""
+}
+
+function validate_arguments {
+
+ if [[ $GOPRO_DEVICE ]] && [[ $GOPRO_DEVICE_PATTERN ]]; then
+ red "-p | --device-pattern and -d | --device are mutually exclusive"
+ exit 1
+ fi
+
+ if [[ $GOPRO_DEVICE ]] || [[ $GOPRO_DEVICE_PATTERN ]] && [[ $GOPRO_IP ]]; then
+ yellow "When an IP is provided the options for -p | --device-pattern and -d | --device ignored"
+ fi
+
+ if [[ ${GOPRO_AUTOSTART} -eq 1 ]] && [[ ${GOPRO_PREVIEW} -eq 1 ]]; then
+ red "-v | --preview and -a | --autostart are mutually exclusive"
+ exit 1
+ fi
+
+ if [[ ${GOPRO_PREVIEW} -eq 1 ]] && [[ ! $GOPRO_USER ]]; then
+ red "-r | --preview needs -u | --user. Please provide it with the mentioned flags"
+ exit 1
+ fi
+
+ if [[ ${GOPRO_FOV} == "wide" ]]; then
+ GOPRO_FOV_ID=0
+ elif [[ ${GOPRO_FOV} == "linear" ]]; then
+ GOPRO_FOV_ID=4
+ elif [[ ${GOPRO_FOV} == "narrow" ]]; then
+ GOPRO_FOV_ID=6
+ else
+ red "Please choose either \"wide\", \"linear\", or \"narrow\""
+ exit 1
+ fi
+
+ if [[ ${GOPRO_FOV} -ne "1080" && ${GOPRO_FOV} -ne "720" && ${GOPRO_FOV} -ne "480" ]]; then
+ red "Please choose either \"1080\", \"720\", or \"480\""
+ exit 1
+ fi
+}
+
+function usage {
+cat << EOF
+Usage: $gopro action [options...]
+Options:
+ -n, --non-interactive do not wait for user input. Use this when used in a startup-script/fstab
+
+ -p, --device-pattern provide a device pattern i.e. (enx, lsr) in case the script failed
+ to detect one by itself.
+
+ -d, --device provide a full device name i.e. (enxenx9245589250e7)
+ USE WITH CAUTION. THIS CHANGES EVERY TIME YOU REBOOT/RECONNECT THE CAMERA
+ THIS OPTION IS NOT SUITABLE FOR AUTOMATION!
+
+ -r, --resolution select the resolution you would like the GoPro to output. "1080", "720", or "480."
+
+ -f, --fov select the FOV you would like to use. "wide", "linear", or "narrow."
+
+ -i, --ip provide a IPv4 address to the GoPro i.e. (172.27.187.52)
+ CAUTION! This may change over time.
+
+ -a, --auto-start automatically start ffmpeg to serve the GoPro as a video device to your operating system.
+ If this flag is omitted, print the corresponding command to run it yourself.
+
+ -v, --preview Just launch a preview in VLC. This will not expose the device to the OS.
+
+ -u, --user VLC can't be started as root, please provide a username you want to run it with. (Typically your 'default/home' user)
+
+ -V, --verbose echo every command that gets executed
+
+ -h, --help display this help
+Commands:
+ webcam start the GoPro in webcam mode
+EOF
+}
+
+function parse_args {
+ # Do not parse a starting --help|-h as an action
+ ! [[ $1 =~ ^- ]] && ACTION=$1 && shift
+
+ while [[ $# -gt 0 ]]; do
+ key="$1"
+ case $key in
+ -V|--verbose)
+ set -x
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ -n|--non-interactive)
+ GOPRO_NON_INTERACTIVE=1
+ ;;
+ -p|--device-pattern)
+ GOPRO_DEVICE_PATTERN=$2
+ shift
+ ;;
+ -d|--device)
+ GOPRO_DEVICE=$2
+ shift
+ ;;
+ -r|--resolution)
+ GOPRO_RESOLUTION=$2
+ shift
+ ;;
+ -f|--fov)
+ GOPRO_FOV=$2
+ shift
+ ;;
+ -i|--ip)
+ GOPRO_IP=$2
+ shift
+ ;;
+ -u|--user)
+ GOPRO_USER=$2
+ shift
+ ;;
+ -a|--auto-start)
+ GOPRO_AUTOSTART=1
+ ;;
+ -v|--preview)
+ DEPS+=('vlc')
+ GOPRO_PREVIEW=1
+ ;;
+ -)
+ _EXTRA_ARGS+=("$(cat $2)")
+ _RAW_INPUT=1
+ shift
+ ;;
+ --)
+ shift
+ _EXTRA_ARGS+=("$@")
+ break
+ ;;
+ *)
+ _EXTRA_ARGS+=("$1")
+ ;;
+ esac
+ shift
+ done
+
+ EXTRA_ARGS="${_EXTRA_ARGS[@]}"
+
+ validate_arguments
+}
+
+function test_DEPS {
+ # bail out if dependencies are not installed.
+ for p in ${DEPS[@]}; do
+ if ! command -v ${p} &> /dev/null
+ then
+ red "${p} could not be found"
+ red "Please use you system's packagemanager to install this dependency and re-run this script"
+ exit 1
+ fi
+ done
+}
+
+function user_confirmation {
+ if [ $GOPRO_NON_INTERACTIVE -ne 1 ] ; then
+ read -p "Please plug in your GoPro and switch it on. If it booted successfully (Charger icon on screen), hit Return"
+ fi
+}
+
+function test_module_probe {
+ # load module
+ if ${module_cmd} &> /dev/null ; then
+ green "${module} was successfully loaded."
+ return 0
+ else
+ red "${module} does not exist. Please either install ${module} or get it from source via https://github.com/umlaeute/v4l2loopback"
+ exit 1
+ fi
+}
+
+function test_module_unload {
+ # unload module
+ if ${module_cmd_unload} &> /dev/null ; then
+ green "${module} was unloaded successfully."
+ return 0
+ else
+ red "${module} could not be unloaded. There is maybe an ffmpeg(or similar) running that uses this module"
+ exit 1
+ fi
+
+}
+
+function test_module_loaded {
+ # test if module is already loaded
+ if lsmod | grep ${module} &> /dev/null ; then
+ green "${module} is loaded!"
+ test_module_unload
+ return 0
+ else
+ green "${module} is not loaded!"
+ return 1
+ fi
+}
+
+function discover_device {
+ local dev
+ if [[ -z $GOPRO_DEVICE_PATTERN ]]; then
+ echo -e "\n"
+ echo "Guessing the GoPro's device name..."
+ echo "I can only make an uneducated guess wrt the name of the interface that the GoPro exposes."
+ echo "For me the name of the interface is 'enxf64854ee7472'. This script will try to discover the device"
+ echo "that was added *last*, as you just plugged in the camera, hence the interface added last should be the one we're looking for."
+ dev=$(ip -4 --oneline link | grep -v "state DOWN" | grep -v LOOPBACK | grep -v "NO-CARRIER" | cut -f2 -d":" | tail -1 | xargs)
+
+ else
+ echo "Using provided device pattern ${GOPRO_DEVICE_PATTERN}"
+ dev=$(ip -4 token | grep ${GOPRO_DEVICE_PATTERN} | tail -1 | sed -e s"/token :: dev//" | sed -e 's/^[[:space:]]*//')
+ fi
+
+ if [[ -z ${dev} ]]; then
+ echo -e "\n"
+ echo "Could not discover a interface. Please restart the script by providing the device or the device pattern that the GoPro exposes (use 'ip addr' for that)"
+ echo "i.e. gopro webcam -d enx123123123"
+ echo "or"
+ echo "i.e. gopro webcam -p lxr"
+ exit 1
+ fi
+
+ green "\nDiscovered: ${dev}."
+ GOPRO_DEVICE=${dev}
+}
+
+function find_gopro_ip {
+
+ if [[ ! ${GOPRO_IP} ]]; then
+ yellow "Using ${GOPRO_DEVICE} to discover the GOPRO_IP."
+ ip=$(ip -4 addr show dev ${GOPRO_DEVICE} | grep -Po '(?<=inet )[\d.]+')
+ if [[ -z ${ip} ]]; then
+ red "Could not automatically discover a valid GOPRO_IP. Use the '-p, -d or -i' option to provide more information. (see --help for more information)"
+ exit 1
+ fi
+ green "Found ${ip}"
+ GOPRO_IP=${ip}
+ fi
+
+ echo "To control the GoPro, we need to contact another interface (GOPRO_IP ending with .51).. Adapting internally.."
+ # For whatever reason the gopro server ends on .51
+ mangled_ip=$(echo ${GOPRO_IP} | awk -F"." '{print $1"."$2"."$3".51"}')
+ green "Now using this GOPRO_IP internally: ${mangled_ip}"
+
+ GOPRO_INTERFACE_IP=$mangled_ip
+}
+
+function start_gopro_webcam_mode {
+
+ local response
+ # Switching to the GoPro Webcam mode
+ response=$(curl -s ${GOPRO_INTERFACE_IP}${START_PATH}${GOPRO_RESOLUTION})
+ if [ $? -ne 0 ]; then
+ red "Error while starting the Webcam mode. # TODO Useful message."
+ exit 1
+ fi
+ echo $response
+ if [[ -z "${response}" ]]; then
+ red "Did not receive a valid response from your GoPro. Please try again to run this script, timing is sometimes crucial."
+ exit 1
+ fi
+ response=$(curl -s ${GOPRO_INTERFACE_IP}${FOV_PATH}${GOPRO_FOV_ID})
+ echo $response
+ if [[ -z "${response}" ]]; then
+ red "Did not receive a valid response from your GoPro. Please try again to run this script, timing is sometimes crucial."
+ exit 1
+ fi
+
+ green "Sucessfully started the GoPro Webcam mode. (The icon on the Camera should have changed)"
+}
+
+function start_webcam {
+
+ if [[ ! ${GOPRO_DEVICE} ]] && [[ ! ${GOPRO_IP} ]]; then
+ discover_device
+ fi
+
+ find_gopro_ip
+
+ start_gopro_webcam_mode
+
+ expose_device
+}
+
+function expose_device {
+
+ if [[ ${GOPRO_AUTOSTART} -eq 1 ]]; then
+ echo "Starting ffmpeg.."
+ ffmpeg -nostdin -threads 1 -i 'udp://@0.0.0.0:8554?overrun_nonfatal=1&fifo_size=50000000' -f:v mpegts -fflags nobuffer -vf format=yuv420p -f v4l2 /dev/video42
+ elif [[ ${GOPRO_PREVIEW} -eq 1 ]]; then
+ echo "Starting preview.."
+ start_preview
+ exit 0
+ else
+ info_only
+ exit 0
+ fi
+}
+
+function start_preview {
+
+ echo -e "To test this try this command(vlc needs to be installed): \n"
+ sudo -u $GOPRO_USER vlc -vvv --network-caching=300 --sout-x264-preset=ultrafast --sout-x264-tune=zerolatency --sout-x264-vbv-bufsize 0 --sout-transcode-threads 4 --no-audio udp://@:8554
+}
+
+function info_only {
+ echo -e "\n\nYou should be ready to use your GoPro on your prefered videostreaming tool. Have Fun!"
+
+ echo -e "\n\nIf you want to use the GoPro in your prefered Video conferencing software (browser and apps works alike) pipe the UDP stream to a video device (that was created already) with this command: \n"
+ green "ffmpeg -nostdin -threads 1 -i 'udp://@0.0.0.0:8554?overrun_nonfatal=1&fifo_size=50000000' -f:v mpegts -fflags nobuffer -vf format=yuv420p -f v4l2 /dev/video42"
+
+ echo -e "\nTo get a preview of the output in vlc you can run this command"
+ echo -e "To test this try this command(vlc needs to be installed): \n"
+ green "vlc -vvv --network-caching=300 --sout-x264-preset=ultrafast --sout-x264-tune=zerolatency --sout-x264-vbv-bufsize 0 --sout-transcode-threads 4 --no-audio udp://@:8554"
+}
+
+
+main() {
+
+ globals
+ parse_args "$@"
+ run_args
+ case $ACTION in
+ help)
+ usage
+ ;;
+ webcam)
+ # check if sudo/root
+ permission_check
+
+ # If module is loaded already, unload it, to maintain idempotency.
+ test_module_loaded
+
+ # modprobe the needed kernel module
+ test_module_probe
+
+ # prompt to plug in the cable and turn on the device
+ user_confirmation
+
+ # Try to detect the correct interface and start the webcam mode
+ start_webcam
+ ;;
+ version)
+ echo version: $VERSION
+ exit 0
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+}
+
+main "$@"
diff --git a/gopro-webcam.install b/gopro-webcam.install
new file mode 100644
index 000000000000..e2b1ce2c2867
--- /dev/null
+++ b/gopro-webcam.install
@@ -0,0 +1,32 @@
+## arg 1: the new package version
+#pre_install() {
+ # do something here
+#}
+
+## arg 1: the new package version
+post_install() {
+ systemctl daemon-reload
+ udevadm control --reload-rules && udevadm trigger
+}
+
+## arg 1: the new package version
+## arg 2: the old package version
+#pre_upgrade() {
+ # do something here
+#}
+
+## arg 1: the new package version
+## arg 2: the old package version
+#post_upgrade() {
+ # do something here
+#}
+
+## arg 1: the old package version
+#pre_remove() {
+ # do something here
+#}
+
+## arg 1: the old package version
+#post_remove() {
+ # do something here
+#}
diff --git a/gopro_webcam.service b/gopro_webcam.service
new file mode 100644
index 000000000000..960beb99f637
--- /dev/null
+++ b/gopro_webcam.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=GoPro Webcam start script
+After=network-online.target
+Wants=network-online.target systemd-networkd-wait-online.service
+
+[Service]
+ExecStart=/usr/local/sbin/gopro webcam -p enx -a -n
+Restart=on-failure
+RestartSec=15s
+
+[Install]
+WantedBy=multi-user.target \ No newline at end of file
diff --git a/install.sh b/install.sh
new file mode 100755
index 000000000000..08b35aee01f5
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[0;33m'
+NC='\033[0m' # No Color
+
+function red {
+ printf "${RED}$@${NC}\n"
+}
+
+function green {
+ printf "${GREEN}$@${NC}\n"
+}
+
+function yellow {
+ printf "${YELLOW}$@${NC}\n"
+}
+
+cp gopro /usr/local/sbin/
+
+chmod +x /usr/local/sbin/gopro
+
+yellow "**********************"
+printf "\n\n"
+green "The GoPro install script succeeded"
+green "Run with with: "
+green "sudo gopro"
+printf "\n\n"
+yellow "**********************"
diff --git a/prepare_webcam.sh b/prepare_webcam.sh
new file mode 100644
index 000000000000..4493aa577f62
--- /dev/null
+++ b/prepare_webcam.sh
@@ -0,0 +1,175 @@
+#!/bin/bash
+
+
+###################################################################
+#Author :Joshua Schmid
+#Email :jxs@posteo.de
+###################################################################
+
+# If run with -vv
+# set -x
+
+
+
+cat << EOF
+Leaving this here to maintain backwards compatibility to any users who may just do a backwards search in their history to re-run this script.
+
+Just FYI, there is a new version of the script with more functionality, including:
+
+* Provide a device pattern for which look for
+* Provide a device directly
+* Provide an IP
+* Auto-start and Preview mode.
+* and more..
+
+All of these features will hopefully simplify using a GoPro as a camera in the day-to-day life by allowing it to run automated in a start-up script.
+
+If you wish to use the new version just check the Github repository. The README should be updated.
+EOF
+
+
+
+
+deps=( "ffmpeg" )
+module="v4l2loopback"
+module_cmd="modprobe v4l2loopback exclusive_caps=1 card_label='GoproLinux' video_nr=42"
+module_cmd_unload="modprobe -rf v4l2loopback"
+
+start_path="/gp/gpWebcam/START"
+stop_path="/gp/gpWebcam/STOP"
+
+if [ "$EUID" -ne 0 ]
+ # the script needs root/sudo
+ then echo "Please run as root or with sudo"
+ exit 1
+fi
+
+function test_deps {
+ # bail out if dependencies are not installed.
+ for p in ${deps[@]}; do
+ if ! command -v ${p} &> /dev/null
+ then
+ echo "${p} could not be found"
+ echo "Please use you system's packagemanager to install this dependency and re-run this script"
+ exit 1
+ fi
+ done
+}
+
+
+function user_confirmation {
+
+ read -p "Please plug in your GoPro and switch it on. If it booted successfully (Charger icon on screen), hit Return"
+}
+
+
+function test_module_probe {
+ # load module
+ if ${module_cmd} &> /dev/null ; then
+ echo ${module} was successfully loaded.
+ return 0
+ else
+ echo ${module} does not exist. Please either install ${module} or get it from source via https://github.com/umlaeute/v4l2loopback
+ exit 1
+ fi
+}
+
+function test_module_unload {
+ # unload module
+ if ${module_cmd_unload} &> /dev/null ; then
+ echo ${module} was unloaded successfully.
+ return 0
+ else
+ echo ${module} could not be unloaded.
+ exit 1
+ fi
+
+}
+
+function test_module_loaded {
+ # test if module is already loaded
+ if lsmod | grep ${module} &> /dev/null ; then
+ echo ${module} is loaded!
+ test_module_unload
+ return 0
+ else
+ echo ${module} is not loaded!
+ return 1
+ fi
+}
+
+
+
+function find_gopro_interface {
+
+ printf "\n\n"
+ echo "I can only make an uneducated guess wrt the name of the interface that the GoPro exposes."
+ echo "For me the name of the interface is 'enxf64854ee7472'. This script will try to discover the device"
+ echo "that was added *last*, as you just plugged in the camera, hence the interface added last should be the one we're looking for."
+
+ dev=$(ip -4 token | tail -1 | sed -e s"/token :: dev//" | sed -e 's/^[[:space:]]*//')
+
+ if [ -z ${dev} ]; then
+ echo "Could not discover a interface. Please restart the script by providing the device that the GoPro exposes (use 'ip addr' for that)"
+ exit 1
+ fi
+ echo -e "\nDiscovered: ${dev}."
+
+ echo "Using this to discover the IP."
+ ip=$(ip -4 addr show dev ${dev} | grep -Po '(?<=inet )[\d.]+')
+ echo "Found ${ip}"
+
+ if [ -z ${ip} ]; then
+ echo "Could not discover a valid IP. # TODO a meaningful error message of what to do or how to proceed"
+ exit 1
+ fi
+
+ echo "To control the GoPro, we need to contact another interface (IP ending with .51).. Adapting internally.."
+ # For whatever reason the gopro server ends on .51
+ mangled_ip=$(echo ${ip} | awk -F"." '{print $1"."$2"."$3".51"}')
+ echo "Now using this IP internally: ${mangled_ip}"
+
+ # Switching to the GoPro Webcam mode
+ response=$(curl -s ${mangled_ip}${start_path})
+ if [ $? -ne 0 ]; then
+ echo "Error while starting the Webcam mode. # TODO Useful message."
+ exit 1
+ fi
+ echo $response
+ if [ -z "${response}" ]; then
+ echo "Did not receive a valid response from your GoPro. Please try again to run this script, timing is somethimes crucial."
+ exit 1
+ fi
+
+ echo "Sucessfully started the GoPro Webcam mode. (The icon on the Camera should have changed)"
+}
+
+
+function end_msg {
+
+ echo -e "\n\nYou should be ready to use your GoPro on your prefered videostreaming tool. Have Fun!"
+
+ echo -e "To test this try this command(vlc needs to be installed): \n"
+ echo "vlc -vvv --network-caching=300 --sout-x264-preset=ultrafast --sout-x264-tune=zerolatency --sout-x264-vbv-bufsize 0 --sout-transcode-threads 4 --no-audio udp://@:8554"
+
+ echo -e "\n\nIf you want to use the GoPro in your prefered Video conferencing software (browser and apps works alike) pipe the UDP stream to a video device (that was created already) with this command: \n"
+ echo "ffmpeg -nostdin -threads 1 -i 'udp://@0.0.0.0:8554?overrun_nonfatal=1&fifo_size=50000000' -f:v mpegts -fflags nobuffer -vf format=yuv420p -f v4l2 /dev/video42"
+
+ exit 0
+
+}
+
+# If module is loaded already, unload it, to maintain idempotency.
+test_module_loaded
+
+# modprobe the needed kernel module
+test_module_probe
+
+# prompt to plug in the cable and turn on the device
+user_confirmation
+
+# Try to detect the correct interface and start the webcam mode
+find_gopro_interface
+
+# lastly, print the optional next steps to the user
+end_msg \ No newline at end of file