Skip to content

Audio video

capture video

This is a setup for capturing video8 tapes to mp4. A naive attempt would be to open up vlc and capture it with that, but this simply will fail in producing good footage. The audio will not be in sync and as soon as some distortion or bad tape (snow) hits the complete recording disappears and never syncs back again even if the camera itself show good footage again.

So this page explains why and how to do it correctly : visit

Of course i tried the commands directly but it might be a good exercise to read the whole document. Or try the next script, i called it capture.sh and it's in the home/bin directory. The settings at the top of the file are those i got from commands explained below the script.

script
VIDEO_CAPABILITIES="video/x-raw, format=(string)YUY2, width=(int)720, height=(int)576, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)25/1"
VIDEO_DEVICE=/dev/video0
AUDIO_DEVICE=hw:2,0
AUDIO_CAPABILITIES="audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)48000, channels=(int)2, channel-mask=(bitmask)0x0000000000000003"

#gst-launch-1.0 \
    #v4l2src device=$VIDEO_DEVICE \
        #! $VIDEO_CAPABILITIES \
        #! mux. \
    #alsasrc device=$AUDIO_DEVICE \
        #! $AUDIO_CAPABILITIES \
        #! mux. \
    #avimux name=mux \
        #! filesink location=test-$( date --iso-8601=seconds ).avi


gst-launch-1.0 -q -e \
    v4l2src device=$VIDEO_DEVICE \
        ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 \
        ! $VIDEO_CAPABILITIES \
        ! videoconvert \
        ! x264enc interlaced=true pass=quant quantizer=0 speed-preset=ultrafast byte-stream=true \
        ! progressreport update-freq=1 \
        ! mux. \
    alsasrc device=$AUDIO_DEVICE \
        ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 \
        ! $AUDIO_CAPABILITIES \
        ! audioconvert \
        ! flacenc \
        ! mux. \
    matroskamux name=mux min-index-interval=1000000000 \
        ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 \
        ! filesink location=test-$( date --iso-8601=seconds ).mkv

I used a video camera from marktplaats and this capture-usb card : WiseGoods - Premium Video Capture Grabber USB 2.0 - Audio + Video Grabber - Video Capture Board (bol.com: visit).

It seems to work flawlessly. It might be that other cards give better colors/quality who knows.

Note that the commented out section was just performing very bad, it says that the sound could not keep up, so the second gst-launch uses a lot more options with caching and encoding. This second part seems to work perfectly in capturing the video as-is, so the audio is synced correctly and it does not lose track when the video start snowing.

Also you can run this command to capture the complete tape and then chop it up in bits.

setup

To get the settings shown in the script, first install the tools mentioned:

install gstreamer
apt-get install gstreamer1.0-tools mpv v4l-utils ffmpeg

Now you can find the settings with these commands :

settings
# VIDEO_DEVICE, view the output and decide which one it should be : (/dev/videoX)
for VIDEO_DEVICE in /dev/video* ; do echo -e "nn$VIDEO_DEVICEn" ; v4l2-ctl --device=$VIDEO_DEVICE --list-inputs ; done
# AUDIO_DEVICE, again you decide, (hw:[visit](card),[visit](subdevice)) 
arecord -l 
# for the next commands you need to fill the DEVICE variables first
# VIDEO_CAPABILITIES : pick the best from the list presented, or try some of them 
export VIDEO_DEVICE=/dev/video0
gst-launch-1.0 --gst-debug=v4l2src:5 v4l2src device=$VIDEO_DEVICE ! fakesink 2>&1 | sed -une '/caps of src/ s/[:;] /n/gp'
CTLR-C # because it will hang/block !
# AUDIO_CAPABILITIES : 
export AUDIO_DEVICE=hw:2,0
kees@hoek:~$ gst-launch-1.0 --gst-debug=alsa:5 alsasrc device=$AUDIO_DEVICE ! fakesink 2>&1 | sed -une '/returning caps/  s/[s;] /n/gp'

Now you fill the capabilities with the complete line from the output, but enclosed in quotes. Exact examples are of course shown in the capture.sh script before.

I would suggest not to add ant transcoding just yet, just get the video into .mkv format and then transcode that. See next chapter.

transcoding

To avoid bad capture, the transcoding step is done separately, this line seems to do a good job :

transcoding
1
2
3
4
5
6
7
8
ffmpeg -i file:test-2021-04-04T09:05:00+02:00.mkv wintersport.mp4
ls -l 
total 111595000
-rw-r--r-- 1 kees kees 40720888175 Apr  3 22:12 test-2021-04-03T20:48:03+02:00.mkv
-rw-r--r-- 1 kees kees 17088480089 Apr  3 22:50 test-2021-04-03T22:16:29+02:00.mkv
-rw-r--r-- 1 kees kees 25038557234 Apr  4 10:14 test-2021-04-04T09:05:00+02:00.mkv
-rw-r--r-- 1 kees kees 29426524957 Apr  4 11:30 test-2021-04-04T10:18:52+02:00.mkv
-rw-r--r-- 1 kees kees  1998786901 Apr  4 11:58 wintersport.mp4

As you can see, a reduction in size of more than 10 times. The video quality is still fine, maybe even tighter transcoding should do ?

castnow

This is an easier command than vlc (later) so install it with :

castnow
sudo npm install castnow -g
castnow video.mp4

Now this will go through some stages and then end in 'playing' or 'idle'. When idle you will see a black screen with the chromecast logo and nothing more. You need to re-encode your video with ffmpeg.

There is a script that says to convert it ok here : visit In case of dead links, the script is :

script
#! /bin/bash

# Batch Convert Script by StevenTrux
# The Purpose of this Script is to batch convert any video file to mp4 or mkv format for chromecast compatibility
# this script only convert necessary tracks if the video is already
# in H.264 format it won't convert it saving your time!

# Put all video files need to be converted in a folder!
# the name of files must not have " " Space!
# Rename the File if contain space 

# Variable used:
# outmode should be mp4 or mkv
# sourcedir is the directory where to be converted videos are
# indir is the directory where converted video will be created

# usage:
#########################
# cast.sh mp4 /home/user/divx /home/user/chromecastvideos
# or
# cast.sh mkv /home/user/divx /home/user/chromecastvideos
#########################

# working mode
outmode=$1
# check output mode
if [[ $outmode ]]; then
if [ $outmode = "mp4" ] || [ $outmode = "mkv" ]
    then 
    echo "WORKING MODE $outmode"
    else
    echo "$outmode is NOT a Correct target format. You need to set an output format! like cast.sh mp4 xxxx or cast.sh mkv xxxx"
    exit
fi
else
echo "Working mode is missing. You should set a correct target format like mp4 or mkv"
exit
fi

# Source dir
sourcedir=$2
if [[ $sourcedir ]]; then 
     echo "Using $sourcedir as Input Folder"
    else
     echo "Error: Check if you have set an input folder"
     exit
fi

# Target dir
indir=$3
if [[ $indir ]]; then 
if mkdir -p $indir/castable
    then
     echo "Using $indir/castable as Output Folder"
    else
     echo "Error: Check if you have the rights to write in $indir"
     exit
fi
    else
     echo "Error: Check if you have set an output folder"
     exit
fi

# set format
if [ $outmode=mp4 ]
    then
     outformat=mp4
    else
     outformat=matroska
fi

# Check FFMPEG Installation
if ffmpeg -formats > /dev/null 2>&1 
    then
     ffversion=`ffmpeg -version 2> /dev/null | grep ffmpeg | sed -n 's/ffmpegs//p'`
     echo "Your ffmpeg verson is $ffversion"
    else
     echo "ERROR: You need ffmpeg installed with x264 and libfdk_aac encoder"
     exit
fi

if ffmpeg -formats 2> /dev/null | grep "E mp4" > /dev/null
    then
     echo "Check mp4 container format ... OK"
    else
     echo "Check mp4 container format ... NOK"
     exit
fi

if ffmpeg -formats 2> /dev/null | grep "E matroska" > /dev/null
        then
         echo "Check mkv container format ... OK"
        else
         echo "Check mkv container format ... NOK"
         exit
fi

if ffmpeg -codecs 2> /dev/null | grep "libfdk_aac" > /dev/null
        then
         echo "Check AAC Audio Encoder ... OK"
        else
         echo "Check AAC Audio Encoder ... NOK"
         exit
fi

if ffmpeg -codecs 2> /dev/null | grep "libx264" > /dev/null
        then
         echo "Check x264 the free H.264 Video Encoder ... OK"
        else
         echo "Check x264 the free H.264 Video Encoder ... NOK"
         exit
fi

echo "Your FFMpeg is OK Entering File Processing"

################################################################
cd "$sourcedir"
for filelist in `ls`
do
    if ffmpeg -i $filelist 2>&1 | grep 'Invalid data found'     #check if it's video file
       then
       echo "ERROR File $filelist is NOT A VIDEO FILE can be converted!"
       continue    

    fi

    if ffmpeg -i $filelist 2>&1 | grep Video: | grep h264       #check video codec
       then
        vcodec=copy
       else
        vcodec=libx264
    fi

    if ffmpeg -i $filelist 2>&1 | grep Video: | grep "High 10"  #10 bit H.264 can't be played by Hardware.
       then
        vcodec=libx264
    fi

    if [ ffmpeg -i $filelist 2>&1 | grep Audio: | grep aac ] || [   ffmpeg -i $filelist 2>&1 | grep Audio: | grep mp3 ] #check audio codec
       then
        acodec=copy
       else
        acodec=libfdk_aac
    fi

        echo "Converting $filelist"
    echo "Video codec: $vcodec Audio codec: $acodec Container: $outformat" 

# using ffmpeg for real converting
    echo "ffmpeg -i $filelist -y -f $outformat -acodec $acodec -ab 192k -ac 2 -absf aac_adtstoasc -async 1 -vcodec $vcodec -vsync 0 -profile:v main -level 3.1 -qmax 22 -qmin 20 -x264opts no-cabac:ref=2 -threads 0 $indir/castable/$filelist.$outmode"
    ffmpeg -i $filelist -y -f $outformat -acodec $acodec -ab 192k -ac 2 -absf aac_adtstoasc -async 1 -vcodec $vcodec -vsync 0 -profile:v main -level 3.1 -qmax 22 -qmin 20 -x264opts no-cabac:ref=2 -threads 0 $indir/castable/$filelist.$outmode


done
    echo ALL Processed!

###################
echo "DONE, your video files are chromecast ready"
exit

However in this form it complains about an error in 'main' and so i deleted the option -profile:v main from the ffmpeg commandline so in my script it becomes :

script
1
2
3
4
5
#!/bin/bash

for i in *.mkv; do
    ffmpeg -i "$i" -vf "subtitles=${i/.mkv/-nl.srt}:charenc=ISO-8859-1" -y -f mp4 -acodec libfdk_aac -ab 192k -ac 2 -absf aac_adtstoasc -async 1 -vsync 0  -level 3.1 -qmax 22 -qmin 20 -x264opts no-cabac:ref=2 -threads 0 "${i/.mkv/.mp4}";
done

Note that this version is needed for hard-coding subtitles (see later on). This runs in about speed 1.0 so you are in for a wait. If you don't need subtitles and think the vcodec is ok. you could use -vcodec copy where the speed goes to 34.0 x

Now if you have a standard ffmpeg you will be missing aac codec and have to recompile ffmpeg. For that this guide worked fine for me : visit

chromecast vlc

vlc 3.0 has native support for playing files on chromecast. However upto now i only got it working via the GUI interface. Just start the file you want to play and then switch to chromecast with :

chromecast
vlc movie.mp4
# playback -> renderer -> chromecast device

commandline interface

I have not got that running, but here is at least a commandline that attempts to do so :

chromecast
cvlc --sout="#chromecast{ip=192.168.2.21}" movie.mp4

It starts and even blanks the tv screen, but then it keeps sending lines like this :

output
1
2
3
4
5
[00007f9bf40026b0] stream_out_chromecast access out warning: httpd buffer full: dropping 52578B
[00007f9bf40026b0] stream_out_chromecast access out warning: httpd buffer full: dropping 33920B
[00007f9bf40026b0] stream_out_chromecast access out warning: httpd buffer full: dropping 45419B
[00007f9bf40026b0] stream_out_chromecast access out warning: httpd buffer full: dropping 33266B
[00007f9bf40026b0] stream_out_chromecast access out warning: httpd buffer full: dropping 43756B

However, starting from vlc and using the menu works, so there MUST be a solution. And there is, i made this script to help remembering the commandline :

cvlc
#~/bin/play_cast.sh
cvlc --sout="#chromecast{ip=192.168.2.21}" --demux-filter=demux_chromecast $1

cvlc is the commandline version of vlc, it does not seems to need the certificate handling below and it does need the subtitles to be merged into the mp4 file as shown in the section below that.

certificate warning

Or is it fatal ?!

gnutls tls client error: Certificate verification failure: The certificate is NOT trusted. The certificate issuer is unknown. The name in the certificate does not match the expected

You can fix this by downloading the certificate :

warning
1
2
3
4
5
6
7
8
9
#To accept the Chromecast certificate:
#1. Get the certificate with gnutls-cli
sudo apt-get install gnutls-bin
gnutls-cli --save-cert=chromecast.pem 192.168.2.21:8009

#2. Start VLC with the --gnutls-dir-trust option
vlc -vv --gnutls-dir-trust=/home/$USER --sout="#chromecast{ip=192.168.2.21}" [visit](video file)

#3. A pop-up window appears with a "Insecure site" warning. Here you can  accept the certificate.

add an srt to mp4

Since chromecast does not support subtitle mixing, you need to physically add them to the mkv/mp4 file. The command line for this is :

To really hardcode it into the mp4 file you can use this, but it takes a lot more time because it is mixed into the video frames.

ffmpeg
ffmpeg -i wildlife.wmv -vf "subtitles=subtitles.srt:charenc=ISO-8859-1" videowithSubtitles.wmv

The charenc is needed if the srt contains unicode characters. The ones i uses all contained a copyright sign in the end so just always include it.

A script that converts .mp4 files automatically if you name the .srt the same :

subtitles
1
2
3
4
5
#!/bin/bash

for i in *.mp4; do
    ffmpeg -i "$i" -vf "subtitles=${i/.mp4/.srt}:charenc=ISO-8859-1"   "${i/.mp4/.dutch.mp4}";
done

This next way does NOT work with chromecast. It still adds the subs as a separate 'track'.

But.. this is faster and works well with players outside chromecast.

fast adding subs
ffmpeg -i infile.mkv -i infile.srt -c copy -c:s mov_text outfile.mp4

I use it like this because my input file was in fact mkv, using mp4 as output works very fast. That is also the problem, the subtitles are now embedded in the outfile.mp4 , but still as a separate 'track'. mplayer shows them perfectly without the .srt file being around, but vlc refuses to show them.

To test if a video is actually chromecast-prepared you can start it with -noautosub and -nosub

noautosub
1
2
3
4
5
6
# to disable taking the subtitles from an .srt file 
mplayer -noautosub file.mp4
# to disable taking the subtitles if embedded as separate track
mplayer -nosub file.mp4
# so if this still shows subtitles, they are realy part of the .mp4
mplayer -nosub -noautosub file.mp4

This last command should show you how it shows in chromecast..

mp3splt

A tool for splitting mp3 on silence detection :

split on gaps
mp3plit -s album.mp3

For albums that are offered as complete album on youtube you can take these steps. :

playlist version
1
2
3
4
5
6
# download from youtube in best audio is mostly type 140
youtube-dl -f 140 [visit](url)
# now you have m4a so use ~/bin/m4a.sh
m4a.sh 
# now you also have mp3, then split
mp3splt -s album.mp3

splitting cue + ape files

splitting cue and ape
sudo aptitude install flac shntool cuetools

Now chances are you cannot read the .ape file format, but there is an easy way to make a flac file from it with ffmpeg, so it will be a two step process.

example
ffmpeg -i Nightwish.ape -acodec flac Nightwish.flac
shntool split -f Nightwish.cue -t '%n. %t' -o flac Nightwish.flac

Generic command when you already have cue + flac files :

shntool split
shntool split -f *.cue -t '%n. %t' -o flac *.flac

Mplayer

A great player, for now i have no issues to report.

MEncoder

Here is a list if formats that i got working (or not) on my philips dvd player. Well.... list....

Not playing

1920 800
VIDEO:  [H264]  1920x800  24bpp  23.976 fps  1840.8 kbps (224.7 kbyte/s)

Working

624 336
VIDEO:  [XVID]  624x336  24bpp  25.000 fps  300.4 kbps (36.7 kbyte/s)

Conversion

convert frames per second

resample
mencoder Jonah.Hex.2010.1080p.BrRip.x264.YIFY.mp4 -mf fps=25 -o 25.avi -oac pcm -ovc lavc

convert scale

rescale
mencoder Jonah.Hex.2010.1080p.BrRip.x264.YIFY.mp4 -o scale.avi -oac pcm -ovc lavc -vf scale=624:336

I had a problem with resolutions 810x400 (or something like that) so stick to a more standard one. A working script at this point that also removes internal (English) subtitles is :

script
# remove conflicting files
rm -f divx2pass.log frameno.avi

# rip audio track (bitrate: 128, gain: 0)
nice -n 3 mencoder -sid 42 -oac mp3lame -lameopts mode=2:cbr:br=128:vol=0 \
 -ovc frameno -o frameno.avi  input.mp4

# video track (pass: 1, bitrate: 25)
nice -n 3 mencoder -sid 42 -sws 2 -oac mp3lame -ovc lavc \
 -lavcopts vcodec=mpeg4:vhq:vpass=1 \
 -ffourcc XVID -vf scale=720:480  input.mp4 -o /dev/null

# video track (pass: 2, bitrate: 25)
nice -n 3 mencoder -sid 42 -sws 2 -oac mp3lame -ovc lavc \
 -lavcopts vcodec=mpeg4:vhq:vpass=2 \
 -ffourcc XVID -vf scale=720:480  input.mp4 -o "movie.avi"

# done

Very rude right now, you need to name your input file input.mp4 and it produces "movie.avi" I will make it take arguments later on .

Videolan VLC

vlc has an option to save youtube video to disk:

vlc
media->"convert/Save"->network

Past the url from your browser and click convert, then fill in the name you want to give to the file. However it might not work on newer linux versions. See next chapter.

lua demux error: Couldn't extract youtube video URL, please check for

This occurred on the new linux debian 7.0 installation of vlc, this web page visit says it's due to an older script. So in short, this worked for me :

working
1
2
3
4
5
su
apt-get install curl
cd /usr/lib/vlc/lua/playlist
rm youtube.*
curl "http://git.videolan.org/?p=vlc.git;a=blob_plain;f=share/lua/playlist/youtube.lua;hb=HEAD" -o /usr/lib/vlc/lua/playlist/youtube.lua

mplayer no /dev/dsp

This was at a company where i could locally install mplayer but not play anything because there was no "/dev/dsp". Vlc is definitely not a solution because i want command line, and that cannot skip forward !! A simple solution : use the pulseaudio OSS wrapper, padsp :

padsp
padsp mplayer */* 

Works the same as before ;)

mplayer overread errors

mplayer keeps displaying lines like this :

output
[mp3float * 0x10829d3c0]overread, skip -6 enddists: -5 -5 ... 

This is probably caused by mplayer using another decoder than the track was encoded with. Use -ac (mp3) to get rid of these messages.

-ac
mplayer -ac mp3 record.mp3

youtube-dl

Youtube-dl downloads the best audio and best video and merges them together, you can see that happening. However it regularly creates files that you cannot play with mplayer. :

output
youtube-dl https://www.youtube.com/watch?v=QK8mJJJvaes
[youtube] QK8mJJJvaes: Downloading webpage
[youtube] QK8mJJJvaes: Downloading video info webpage
[youtube] QK8mJJJvaes: Extracting video information
[youtube] QK8mJJJvaes: Downloading MPD manifest
WARNING: Requested formats are incompatible for merge and will be merged into mkv.
[download] Destination: MACKLEMORE & RYAN LEWIS - THRIFT SHOP FEAT. WANZ (OFFICIAL VIDEO)-QK8mJJJvaes.f217.mp4
[download] 100% of 214.21MiB in 00:41
[download] Destination: MACKLEMORE & RYAN LEWIS - THRIFT SHOP FEAT. WANZ (OFFICIAL VIDEO)-QK8mJJJvaes.f251.webm
[download] 100% of 3.89MiB in 00:00
[ffmpeg] Merging formats into "MACKLEMORE & RYAN LEWIS - THRIFT SHOP FEAT. WANZ (OFFICIAL VIDEO)-QK8mJJJvaes.mkv"
Deleting original file MACKLEMORE & RYAN LEWIS - THRIFT SHOP FEAT. WANZ (OFFICIAL VIDEO)-QK8mJJJvaes.f217.mp4 (pass -k to keep)
Deleting original file MACKLEMORE & RYAN LEWIS - THRIFT SHOP FEAT. WANZ (OFFICIAL VIDEO)-QK8mJJJvaes.f251.webm (pass -k to keep)

From the names you can extract the format code : so that's -f 217 and -f 251

So that's :

find format code
217          mp4        1920x1080  DASH video 7921k , avc1.640028, 1fps, video only, 214.21MiB
251          webm       audio only DASH audio  162k , opus @160k, 3.89MiB

But opus is not supported by mplayer, so it's advised to specify the parts yourself options, i created a script file to do that called youtube :

script
youtube-dl -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]' $1

The output for this command will be -f 217 and -f140, so 217 is the same and 140 is the one i always use for audio only :

audio
140          m4a        audio only DASH audio  128k , m4a_dash container, mp4a.40.2@128k (44100Hz), 3.52MiB