From 8fecf681ea9c68ba1e4a97a90e85a0d850f3f9ae Mon Sep 17 00:00:00 2001 From: "C.J. Adams-Collier" Date: Mon, 11 Jan 2016 22:36:18 -0800 Subject: semi-working bridge between webcam mic and default mic --- prepare-videochat.sh | 151 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 122 insertions(+), 29 deletions(-) (limited to 'prepare-videochat.sh') diff --git a/prepare-videochat.sh b/prepare-videochat.sh index 341a8e9..38a36d2 100755 --- a/prepare-videochat.sh +++ b/prepare-videochat.sh @@ -92,6 +92,11 @@ 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. @@ -113,8 +118,6 @@ 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 ### FUNCTIONS @@ -156,7 +159,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 +177,48 @@ start_iw_server() { sleep 2s } +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_CONVERTER="ffmpegcolorspace" +GST_MIMETYPE="video/x-raw-yuv" +GST_FORMAT="format=(fourcc)YV12" + +GST_0_10_MIMETYPE=$GST_MIMETYPE +GST_0_10_FORMAT=$GST_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_CONVERTER="videoconvert" + GST_MIMETYPE="video/x-raw" + GST_FORMAT="format=YV12" +fi + +# 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 +230,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 +288,67 @@ 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 +SINK_NAME="ipwebcam" # Load null-sink if needed -if !(pactl list sinks | grep -q module-null-sink); then - pactl load-module module-null-sink +if !(pactl list sinks | grep -q $SINK_NAME); then + pactl load-module module-null-sink sink_name="$SINK_NAME" sink_properties="device.description='IP\ Webcam'" 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}' ) +SINK_ID=$(pactl list sinks | sed -n -e "/Owner Module:/h; /$SINK_NAME.monitor/{x; s/\s*Owner Module:\s*//g; p; q}") + +#DUPLEX_SINK_NAME="ipwebcam_mic" +#if !(pactl list sinks | grep -q $DUPLEX_SINK_NAME); then +# pactl load-module module-null-sink sink_name="$DUPLEX_SINK_NAME" sink_properties="device.description='IP\ Webcam\ and\ Mic\ MUX',filter.want=echo-cancel" +#fi +#DUPLEX_SINK_ID=$(pactl list sinks | sed -n -e "/Owner Module:/h; /$DUPLEX_SINK_NAME.monitor/{x; s/\s*Owner Module:\s*//g; p; q}") + + +#if !(pactl list modules | grep -q "source=${SINK_NAME}.monitor sink=${DUPLEX_SINK_NAME}"); then +# pactl load-module module-loopback source="${SINK_NAME}.monitor" sink="$DUPLEX_SINK_NAME" +#fi +#SINKMON_LOOP_ID=$(pactl list modules | sed -n -e "/Module #/h; /source=${SINK_NAME}.monitor sink=${DUPLEX_SINK_NAME}/{x; s/\s*Module #\s*//g; p; q}") + +DEFAULT_SINK=$(pacmd dump | mawk '/set-default-sink/ {print $2}') +DEFAULT_SOURCE=$(pacmd dump | mawk '/set-default-source/ {print $2}') + +#if !(pactl list modules | grep -q "source=${DEFAULT_SINK} sink=${DUPLEX_SINK_NAME}"); then +#if !(pactl list modules | grep -q "source=${DUPLEX_SINK_NAME}.monitor sink=${DEFAULT_SINK}"); then +if !(pactl list modules | grep -q "source=${SINK_NAME}.monitor sink=${DEFAULT_SINK}"); then +# pactl load-module module-loopback source=${DEFAULT_SINK} sink="$DUPLEX_SINK_NAME" +# pactl load-module module-loopback source=${DUPLEX_SINK_NAME}.monitor sink="$DEFAULT_SINK" + pactl load-module module-loopback source=${SINK_NAME}.monitor sink="$DEFAULT_SINK" +fi +#DEFAULT_LOOP_ID=$(pactl list modules | sed -n -e "/Module #/h; /source=${DEFAULT_SOURCE} sink=${DUPLEX_SINK_NAME}/{x; s/\s*Module #\s*//g; p; q}") +#DEFAULT_LOOP_ID=$(pactl list modules | sed -n -e "/Module #/h; /source=${DUPLEX_SINK_NAME}.monitor sink=${DEFAULT_SINK}/{x; s/\s*Module #\s*//g; p; q}") +DEFAULT_LOOP_ID=$(pactl list modules | sed -n -e "/Module #/h; /source=${SINK_NAME}.monitor sink=${DEFAULT_SINK}/{x; s/\s*Module #\s*//g; p; q}") + +pactl load-module module-echo-cancel \ + source_name="ipwebcam_efilter" source_master="${SINK_NAME}.monitor" source_properties="device.description='IP\ Webcam\ and\ Mic\ echo\ filter\ source'" \ + sink_name="default_efilter" sink_master="${DEFAULT_SINK}" sink_properties="device.description='IP\ Webcam\ and\ Mic\ echo\ filter\ sink'" \ + aec_method="webrtc" save_aec=1 use_volume_sharing=1 # 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 + sudo apt-get install -y pavucontrol 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'." + info "We will open now pavucontrol. You should leave it open to change the recording device of your video chat program to 'Monitor IP Webcam'. NOTE: make sure that in 'Output Devices' *all* devices are listed, and in the Playback tab the $GSTLAUNCH program sends its audio to the 'IP Webcam'." pavucontrol & fi # 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 +358,35 @@ 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." +info "Using IP Webcam as webcam/microphone through v4l2loopback device $DEVICE. Microphone is directed to $SINK_NAME and multiplexed with ${DEFAULT_SOURCE}. You can now open your videochat app." + +WIDTH=640 +HEIGHT=480 +GST_FPS=5 +DIMENSIONS="width=$WIDTH,height=$HEIGHT" + +GST_0_10_CAPS="$GST_0_10_MIMETYPE,$GST_0_10_FORMAT,$DIMENSIONS" +CAPS="$GST_MIMETYPE,$GST_FORMAT,$DIMENSIONS,framerate=$GST_FPS/1" \ +#sudo v4l2loopback-ctl set-caps $GST_0_10_CAPS $DEVICE + "$GSTLAUNCH" -vt --gst-plugin-spew --gst-debug="$GST_DEBUG" \ - souphttpsrc location="http://$IP:$PORT/videofeed" do-timestamp=true is-live=true \ + 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_CONVERTER \ + ! videoscale \ + ! videorate \ + ! $CAPS \ + ! v4l2sink device="$DEVICE" sync=true \ + souphttpsrc location="$AUDIO_URL" do-timestamp=true is-live=true \ + ! wavparse \ + ! audioconvert \ + ! volume volume=3 \ + ! rglimiter \ + ! pulsesink device="$SINK_NAME" sync=true \ + 2>&1 | tee feed.log info "Disconnected from IP Webcam. Have a nice day!" + +pactl unload-module ${SINK_ID} -- cgit v1.2.3