diff options
author | Antonio García-Domínguez <nyoescape@gmail.com> | 2016-01-13 22:46:41 +0000 |
---|---|---|
committer | Antonio García-Domínguez <nyoescape@gmail.com> | 2016-01-13 22:46:41 +0000 |
commit | c0e57f45c830732db4f2601f069febfd0cd037dd (patch) | |
tree | b0a463ceb3bdbb579b5197a199ca374e31d399e6 | |
parent | 738492d87e4398752213d9738cd2c3e97f37d736 (diff) | |
parent | e1d45cc485265e0fde2d8e189d638e86eeb531fe (diff) |
Merge pull request #21 from LLC-Technologies-Collier/master
much better audio performance, automatic selection of correct audio sink, other features
-rw-r--r-- | .gitignore | 1 | ||||
-rwxr-xr-x | prepare-videochat.sh | 206 |
2 files changed, 157 insertions, 50 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ad69f2a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +feed.log diff --git a/prepare-videochat.sh b/prepare-videochat.sh index 341a8e9..55be954 100755 --- a/prepare-videochat.sh +++ b/prepare-videochat.sh @@ -1,7 +1,10 @@ #!/bin/bash -# Script for using IP Webcam as a microphone/webcam in Ubuntu 13.04 and Arch +# Script for using IP Webcam as a microphone/webcam in Debian Jessie, +# Ubuntu 13.04, 14.04 and Arch + # Copyright (C) 2011-2013 Antonio García Domínguez +# Copyright (C) 2016 C.J. Adams-Collier # Licensed under GPLv3 # Usage: ./prepare-videochat.sh [flip method] @@ -31,8 +34,7 @@ # 1. Does v4l2loopback work properly? # # Try running these commands. You'll first need to install mplayer and -# ensure that your user can write to /dev/video*), and then run these -# commands on one tab: +# ensure that your user can write to /dev/video*). # # sudo modprobe -r v4l2loopback # ls /dev/video* @@ -40,11 +42,9 @@ # sudo modprobe v4l2loopback # ls /dev/video* # (Note down the new devices: let X be the number of the first new device.) -# gst-launch videotestsrc ! v4l2sink device=/dev/videoX -# -# Now go to another tab and use mplayer to play it back: +# v4l2-ctl -D -d /dev/videoX +# gst-launch videotestsrc ! v4l2sink device=/dev/videoX & mplayer -tv device=/dev/videoX tv:// # -# mplayer -tv device=/dev/videoX tv:// # # You should be able to see the GStreamer test video source, which is # like a TV test card. Otherwise, there's an issue in your v4l2loopback @@ -92,12 +92,17 @@ else FLIP_METHOD=none fi +GST_FLIP="! videoflip method=\"$FLIP_METHOD\" " +if [ $FLIP_METHOD = 'none' ]; then + GST_FLIP="" +fi + ### CONFIGURATION # If your "adb" is not in your $PATH, set the full path to it here. # If "adb" is in your $PATH, you don't have to change this option. ADB_PATH=~/bin/android-sdk-linux_x86/platform-tools/adb -if which adb; then +if which adb > /dev/null ; then ADB=$(which adb) else ADB=$ADB_PATH @@ -113,30 +118,35 @@ WIFI_IP=192.168.2.140 # Port on which IP Webcam is listening PORT=8080 -# GStreamer debug string (see gst-launch manpage) -GST_DEBUG=souphttpsrc:0,videoflip:0,ffmpegcolorspace:0,v4l2sink:0,pulse:0 +# Dimensions of video +WIDTH=640 +HEIGHT=480 + +# Frame rate of video +GST_FPS=5 + ### FUNCTIONS has_kernel_module() { - sudo modprobe -q "$1" + sudo modprobe -q "$1" > /dev/null 2>&1 } error() { - zenity --error --text "$@" + zenity --error --text "$@" > /dev/null 2>&1 exit 1 } warning() { - zenity --warning --text "$@" + zenity --warning --text "$@" > /dev/null 2>&1 } info() { - zenity --info --text "$@" + zenity --info --text "$@" > /dev/null 2>&1 } confirm() { - zenity --question --text "$@" + zenity --question --text "$@" > /dev/null 2>&1 } can_run() { @@ -156,7 +166,7 @@ url_reachable() { if ! can_run curl && can_run apt-get; then # Some versions of Ubuntu do not have curl by default (Arch # has it in its core, so we don't need to check that case) - sudo apt-get install curl + sudo apt-get install -y curl fi curl -sI "$1" >/dev/null } @@ -174,13 +184,75 @@ start_iw_server() { sleep 2s } +modid_by_sinkname() { + pacmd list-sinks | grep -e 'name:' -e 'module:' | grep -A1 "name: <$1>" | grep module: | cut -f2 -d: | tr -d ' ' +} + +modid_by_sourcename() { + pacmd list-sources | grep -e 'name:' -e 'module:' | grep -A1 "name: <$1>" | grep module: | cut -f2 -d: | tr -d ' ' +} + + +if can_run lsb_release; then + DIST=`lsb_release -i | awk -F: '{print $2}'` + RELEASE=`lsb_release -r | awk -F: '{print $2}'` +elif [ -f /etc/debian_version ] ; then + DIST="Debian" + RELEASE=`perl -ne 'chomp; if(m:(jessie|testing|sid):){print "8.0"}elsif(m:[\d\.]+:){print}else{print "0.0"}' < /etc/debian_version` +fi + +GST_VER="0.10" +GST_VIDEO_CONVERTER="ffmpegcolorspace" +GST_VIDEO_MIMETYPE="video/x-raw-yuv" +GST_VIDEO_FORMAT="format=(fourcc)YV12" + +GST_AUDIO_MIMETYPE="audio/x-raw-int" +GST_AUDIO_FORMAT="width=16,depth=16,endianness=1234,signed=true" +GST_AUDIO_RATE="rate=44100" +GST_AUDIO_CHANNELS="channels=1" +GST_AUDIO_LAYOUT="" + +GST_1_0_AUDIO_FORMAT="format=S16LE" +GST_0_10_VIDEO_MIMETYPE=$GST_VIDEO_MIMETYPE +GST_0_10_VIDEO_FORMAT=$GST_VIDEO_FORMAT + +if [ $DIST = "Debian" -a `echo "$RELEASE >= 8.0" | bc` -eq 1 ] ||\ + [ $DIST = "Ubuntu" -a `echo "$RELEASE >= 14.04" | bc` -eq 1 ] +then + GST_VER="1.0" + GST_VIDEO_CONVERTER="videoconvert" + GST_VIDEO_MIMETYPE="video/x-raw" + GST_VIDEO_FORMAT="format=YV12" + + GST_AUDIO_MIMETYPE="audio/x-raw" + GST_AUDIO_FORMAT=$GST_1_0_AUDIO_FORMAT + GST_AUDIO_LAYOUT=",layout=interleaved" +fi + +DIMENSIONS="width=$WIDTH,height=$HEIGHT" + +GST_0_10_VIDEO_CAPS="$GST_0_10_VIDEO_MIMETYPE,$GST_0_10_VIDEO_FORMAT,$DIMENSIONS" +GST_VIDEO_CAPS="$GST_VIDEO_MIMETYPE,$GST_VIDEO_FORMAT,$DIMENSIONS,framerate=$GST_FPS/1" +GST_AUDIO_CAPS="$GST_AUDIO_MIMETYPE,$GST_AUDIO_FORMAT$GST_AUDIO_LAYOUT,$GST_AUDIO_RATE,$GST_AUDIO_CHANNELS" +PA_AUDIO_CAPS="$GST_AUDIO_FORMAT $GST_AUDIO_RATE $GST_AUDIO_CHANNELS" + +# GStreamer debug string (see gst-launch manpage) +GST_DEBUG=souphttpsrc:0,videoflip:0,$GST_CONVERTER:0,v4l2sink:0,pulse:0 + ### MAIN BODY # Check if the user has v4l2loopback if ! has_kernel_module v4l2loopback; then - info "The v4l2loopback kernel module is not installed or could not be loaded. I will try to install the kernel module using your distro's package manager. If that doesn't work, please install v4l2loopback manually from github.com/umlaeute/v4l2loopback." - if can_run apt-get; then - sudo apt-get install python-apport v4l2loopback-dkms + info "The v4l2loopback kernel module is not installed or could not be loaded. Attempting to install the kernel module using your distro's package manager." + if [ $DIST = "Debian" ] || [ $DIST = "Ubuntu" ]; then + V4L2LOOPBACK_PKGS="v4l2loopback-dkms" + if [ $DIST = "Ubuntu" ]; then + V4L2LOOPBACK_PKGS="${V4L2LOOPBACK_PKGS} python-apport" + fi + sudo apt-get -y install $V4L2LOOPBACK_PKGS + if [ $? != 0 ]; then + info "Installation failed. Please install v4l2loopback manually from github.com/umlaeute/v4l2loopback." + fi elif can_run yaourt; then yaourt -S v4l2loopback-git fi @@ -192,12 +264,21 @@ if ! has_kernel_module v4l2loopback; then fi fi +# check if the user has the pulse gst plugin installed +if [ ! -f /usr/lib/*/gstreamer-$GST_VER/libgstpulse.so ]; then + if [ $DIST = "Debian" ] || [ $DIST = "Ubuntu" ]; then + sudo apt-get install -y gstreamer${GST_VER}-pulseaudio + elif can_run yaourt; then + echo "we should figure out what package supplies this" + fi +fi + # Use the first "v4l2 loopback" device as the webcam: this should help # when loading v4l2loopback on a system that already has a regular # webcam. if ! can_run v4l2-ctl; then if can_run apt-get; then - sudo apt-get install v4l-utils + sudo apt-get install -y v4l-utils elif can_run pacman; then sudo pacman -S v4l-utils fi @@ -241,38 +322,44 @@ while ! iw_server_is_started; do info "The IP Webcam video feed is not reachable at $VIDEO_URL. Please open IP Webcam in your phone and start the server." done -# Load null-sink if needed -if !(pactl list sinks | grep -q module-null-sink); then - pactl load-module module-null-sink -fi -NULL_SINK=$(LC_ALL=C pactl list sinks | \ - sed -n -e '/Name:/h; /module-null-sink/{x; s/\s*Name:\s*//g; p; q}' ) +DEFAULT_SINK=$(pacmd dump | mawk '/set-default-sink/ {print $2}') +DEFAULT_SOURCE=$(pacmd dump | mawk '/set-default-source/ {print $2}') + +SINK_NAME="ipwebcam" +SINK_ID=$(modid_by_sinkname $SINK_NAME) +ECANCEL_ID=$(modid_by_sinkname "${SINK_NAME}_echo_cancel") -# Install and open pavucontrol as needed -if ! can_run pavucontrol; then - info "You don't have pavucontrol. I'll try to install its Debian/Ubuntu package." - sudo apt-get install pavucontrol +if [ -z $SINK_ID ] ; then + SINK_ID=$(pactl load-module module-null-sink \ + sink_name="$SINK_NAME" \ + $PA_AUDIO_CAPS \ + sink_properties="device.description='IP\ Webcam'") fi -if ! pgrep pavucontrol; then - info "We will open now pavucontrol. You should leave it open to change the recording device of your video chat program to 'Monitor Null Output'. NOTE: make sure that in 'Output Devices' *all* devices are listed, and in the Playback tab the $GSTLAUNCH program sends its audio to the 'Null Sink'." - pavucontrol & + +if [ -z $ECANCEL_ID ] ; then + ECANCEL_ID=$(pactl load-module module-echo-cancel \ + sink_name="${SINK_NAME}_echo_cancel" \ + source_master="$SINK_NAME.monitor" \ + sink_master="$DEFAULT_SINK" \ + $PA_AUDIO_CAPS \ + aec_method="webrtc" save_aec=true use_volume_sharing=true) fi +pactl set-default-source $SINK_NAME.monitor + # Check for gst-launch -GSTLAUNCH=gst-launch -if can_run apt-get; then +GSTLAUNCH=gst-launch-${GST_VER} +if [ $DIST = "Debian" ]; then # Debian - GSTLAUNCH=gst-launch if ! can_run "$GSTLAUNCH"; then info "You don't have gst-launch. I'll try to install its Debian/Ubuntu package." - sudo apt-get install gstreamer-tools + sudo apt-get install -y gstreamer${GST_VER}-tools fi elif can_run pacman; then # Arch - GSTLAUNCH=gst-launch-0.10 if ! can_run "$GSTLAUNCH"; then info "You don't have gst-launch. I'll try to install its Arch package." - sudo pacman -S gstreamer0.10 gstreamer0.10-good-plugins + sudo pacman -S gstreamer${GST_VER} gstreamer${GST_VER}-good-plugins fi fi if ! can_run "$GSTLAUNCH"; then @@ -282,18 +369,37 @@ fi # Start the GStreamer graph needed to grab the video and audio set +e -info "Using IP Webcam as webcam/microphone through v4l2loopback device $DEVICE and PulseAudio sink '$NULL_SINK'. You can now open your videochat app." -"$GSTLAUNCH" -vt --gst-plugin-spew --gst-debug="$GST_DEBUG" \ - souphttpsrc location="http://$IP:$PORT/videofeed" do-timestamp=true is-live=true \ + +#sudo v4l2loopback-ctl set-caps $GST_0_10_VIDEO_CAPS $DEVICE + +"$GSTLAUNCH" -e -vt --gst-plugin-spew \ + --gst-debug="$GST_DEBUG" \ + souphttpsrc location="$VIDEO_URL" do-timestamp=true is-live=true \ ! multipartdemux \ ! jpegdec \ - ! ffmpegcolorspace ! "video/x-raw-yuv, format=(fourcc)YV12" \ - ! videoflip method="$FLIP_METHOD" ! videorate ! "video/x-raw-yuv, framerate=25/1" \ - ! v4l2sink device="$DEVICE" \ - souphttpsrc location="http://$IP:$PORT/audio.wav" do-timestamp=true is-live=true \ - ! wavparse ! audioconvert \ - ! volume volume=3 ! rglimiter \ - ! pulsesink device="$NULL_SINK" sync=false \ - 2>&1 | tee feed.log + $GST_FLIP \ + ! $GST_VIDEO_CONVERTER \ + ! videoscale \ + ! videorate \ + ! $GST_VIDEO_CAPS \ + ! v4l2sink device="$DEVICE" sync=true \ + souphttpsrc location="$AUDIO_URL" do-timestamp=true is-live=true \ + ! $GST_AUDIO_CAPS \ + ! pulsesink device="$SINK_NAME" sync=true \ + 2>&1 > feed.log & + +GSTLAUNCH_PID=$! + +info "IP Webcam video is streaming through v4l2loopback device $DEVICE. +IP Webcam audio is streaming through pulseaudio sink '$SINK_NAME'. +You can now open your videochat app." + +echo "Press enter to end stream" +perl -e '<STDIN>' + +kill $GSTLAUNCH_PID > /dev/null 2>&1 || echo "" +pactl set-default-source ${DEFAULT_SOURCE} +pactl unload-module ${ECANCEL_ID} +pactl unload-module ${SINK_ID} info "Disconnected from IP Webcam. Have a nice day!" |