Gondola: Media server that runs from an old laptop / RaspberryPi
Sick of your kids' DVD's getting scratched and unusable?
Gondola is a media center that is designed to work from an old laptop, or a cheap+silent single board computer (SBC) like a Chip or a Raspberry Pi.
It accomplishes this feat by pre-processing your media into HLS, then serving it using Nginx. Pre-processing can take a very long time eg overnight on a Chip, so the recommended use case for this is to make backups of DVDs that you're likely to watch more than once. Eg your kids' movies, so you don't have to worry about the discs getting scratched.
Configuration is compulsory, and goes into ~/.gondola
It uses TOML format (same as windows INI files). Options include:
root = "~/Some/Folder/Where/I/Want/My/Data/To/Go"
This allows you to disable the transcoding, which is useful to speed up dev.
debugSkipHLS = true
When you dump a movie into the 'New/Movies' folder, the following will work:
* Big.Buck.Bunny.2008.1080p.blah.vob
* Big Buck Bunny 2008 1080p blah.vob
* Big.Buck.Bunny.vob
* Big.Buck.Bunny.2008.deinterlace.vob
* Big.Buck.Bunny.2008.scalecrop1080.vob
* Big.Buck.Bunny.2008.crop1920_940Ratio.vob
* Big.Buck.Bunny.2008.scalecrop1920_940.vob
* Big.Buck.Bunny.2008.scalecrop239letterbox1080.vob
* Big.Buck.Bunny.2008.scalecrop239letterbox1920_940.vob
* !Big Buck Bunny.2008.vob (this is for movies that cannot be found on TMDB; you will need to supply images yourself)
If it finds a year, it assumes the text to the left is the title. Text to the right is ignored, as it's usually resolution/codec/other stuff. Dots/periods are converted to spaces, which it then uses to search TMDB for the movie metadata.
If it cannot find a year, it still searches TMDB to find the movie, but it stands less of a chance finding the correct movie if there's no year.
If it finds 'deinterlace' then it uses FFMPEG to deinterlace the video. This is useful for old DVDs.
If 'scalecrop1080' is found, it scales to 1080p high, then takes only the center 1920 columns, discarding some content to the left and right outside of the 1920. This is handy when you have eg very-widescreen 4k input, and you want it to completely fill your TV, and prefer cropping off the right and left sides a little. Use this if there are no letterbox black bars baked into the input.
Use 'scalecrop1920_940' in the same way you'd use 'scalecrop1080' for wide 4k inputs that you'd like to crop a little off the sides, but is a compromise: You're still letterboxed, just that the black bars are half the height. Probably a good option for epic movies.
Use 'crop1920_940Ratio' similarly to scalecrop1920_940 for inputs that are 1920 wide so you don't want to scale them down, and of eg 1:2.39 ratio, so it crops a bit off the left and right so that it fills the screen a bit more (but not entirely, so you still have the movie effect).
Use 'scalecrop239letterbox1080' for the same purpose as scalecrop1080, however this is for when letterbox black bars are baked into the input. This assumes the part we want to keep after cropping the black bars is 1:2.39 ratio.
Use 'scalecrop239letterbox1920_940' to get the same output as scalecrop1920_940, but if the input has the letterbox bars baked in.
Use 'crop240LetterboxThenUnivisium' to crop out baked-in 1:2.4 letterbox bars, then crop again to univisium 2:1. Useful for DVDs.
Use 'crop235LetterboxThenUnivisiumThen1920' for 4k inputs, to crop out baked-in 1:2.35 letterbox bars, then crop again to univisium 2:1, then scale to 1920x960.
Use 'crop240LetterboxThen169' to crop out baked-in 1:2.40 letterbox bars, then crop again to 16:9.
Use 'crop235LetterboxThen169' to crop out baked-in 1:2.35 letterbox bars, then crop again to 16:9.
For TV shows placed in New/TV
folder, use the following:
* Some.TV.Show.S01E02.DVD.vob
* Some TV Show S01E02 Blah blah blah.vob
* Some TV Show - Episode Name.vob
So long as it can find 'SxxEyy' (for season x episode y), it assumes the show's title is to the left, and ignores anything to the right. It then searches TMDB to find the show's metadata.
If you use the last format (eg there's no SxEy, and there is a -
), it takes a 'best guess' at which season and episode it is. This is useful for shows where the DVD order is different to the TV order. I actually recommend using this when you make backups of your DVDs. The episode name doesn't need to be an exact match, because it does a 'Levenshtein distance' calculation to make a best guess at which episode it is.
But it forces you to confirm it guessed correctly: the file is renamed to the best guess, with a .remove if correct
extension attached. If you're happy with the guess, rename the file to remove the extension, and it'll process as usual. Eg if you upload Seinfeld - Serenity.vob
, it'll rename it to Seinfeld S09E03 The Serenity Now.Seinfeld - Serenity.vob.remove if correct
. The first half of that is the guessed episode's number and it's name according to TMDB, then the original name you gave the file, then the remove_if_correct extension for you to remove as a confirmation that you're happy.
Since the TMDB lookup tends to fail now, you can use the following naming convention:
* !Show name - S1 Season 1 - E2 Episode title.deinterlace.vob
Obviously this will not be able to look up metadata, so it is up to you to provide images in this case.
The name is a (tortured) metaphor: A real gondola transports you down a stream; this Gondola transports your media by streaming it ;)
An Orange Pi PC is a good choice because it has 1GB RAM, which is enough for 1080p transcoding; and it has a good power supply thus can power an external USB HDD.
22x22x25mm adhesive heatsink
sudo apt-get update
<- If you get a lock error, wait 5 mins and try again, it might be auto-updating.sudo apt-get install avahi-daemon
<- This gets bonjour working, so macs can find it.sudo nano /etc/hostname
<- change the host name 'gondola'.sudo nano /etc/hosts
<- change 'orangepipc' to 'gondola' in this file.sudo reboot now
<- applies the hostname change.ssh [email protected]
<- login from your mac.sudo dpkg-reconfigure tzdata
<- set up the timezones.sudo mkdir /media/usb
<- Make a mount point for the external hdd.sudo chown gondola /media/usb
<- Set the permissions for the mount.sudo chgrp gondola /media/usb
sudo nano /etc/fstab
<- Configure the auto-mount.
/dev/sda1 /media/usb auto defaults,noatime,uid=gondola,gid=gondola 0 0
noatime
above makes it not write an updated time when you read, which is faster and causes less wear if it's a flash drive.uid=gondola,gid=gondola
gives the proper permissions if it's a FAT drive.sudo mount -a
<- Auto mount.sudo nano /etc/apt/sources.list
deb http://httpredir.debian.org/debian experimental main
deb http://httpredir.debian.org/debian unstable main
sudo apt-get install git golang lsof ffmpeg nginx
nano ~/.bash_profile
export GOPATH=$HOME/go
source ~/.bash_profile
<- reload the profile
env | grep go
<- test it workedsudo visudo -f /etc/sudoers.d/lsof
gondola ALL = (root) NOPASSWD: /usr/bin/lsof
go get github.com/chrishulbert/gondola
nano ~/.gondola
* Paste root = "/media/usb/Gondola"
~/go/bin/gondola
<- it should say 'Watching for changes'. Do Ctrl+C to close.
sudo nano /lib/systemd/system/gondola.service
Paste the following:
[Unit]
Description=Gondola media server
[Service]
PIDFile=/tmp/gondola.pid
User=gondola
Group=gondola
ExecStart=/home/gondola/go/bin/gondola
[Install]
WantedBy=multi-user.target
sudo systemctl enable gondola
<- make it run on boot
sudo systemctl start gondola
<- make it start now
systemctl status gondola
<- it should be 'active (running)'
sudo journalctl -u gondola
<- use this to view Gondola's logs, should say 'watching for changes'
sudo nano /etc/nginx/sites-available/default
root /var/www/html;
and change line to: root /media/usb/Gondola;
<- customise the path to suit where your hard drive mountssudo nano /etc/nginx/nginx.conf
user www-data;
and change to user gondola;
<- this allows nginx to read your external HDDsudo nginx -s reload
<- apply the nginx config changes.sudo cat /var/log/nginx/error.log
nano ~/.bash_profile
alias l="sudo journalctl -u gondola | tail -n 100"
source ~/.bash_profile
l
anytime you want to see the gondola logs.Get a second hand laptop (you may have one lying around?). I bought a second hand HP Stream 11 for $120 - I recommend this laptop because it's cheap, small, fanless thus silent, and has a small power adapter thus won't use much electricity.
Install Ubuntu. In the installer, set the computer name to 'gondola', and the user 'gondola'.
If you use an HP Stream, some good instructions for installing and tweaking Ubuntu are here.
In Ubuntu settings > Power, under 'when the lid is closed', set it to 'do nothing'. Now your laptop will continue running as a server when closed. Update: In newer versions, you may follow the instructions here to do the same: https://askubuntu.com/a/372616/655394
Connect your external hard drive (my laptop has one USB3 port and one USB2 - ensure you connect to the faster one). Find where it mounts: in my case, it mounts at /media/gondola/KRYTEN. (Kryten is the name of my external drive).
In the terminal, run the following:
sudo apt-get install openssh-server
You should now be able to SSH in from your Mac/PC with the following terminal command:
ssh [email protected]
If that succeeded, you may now connect your laptop to power, close the lid, and tuck it away somewhere with a bit of clear airflow, and follow the remaining instructions using remote SSH:
sudo apt-get install git
No such file or directory: textflag.h
sudo nano /etc/apt/sources.list
deb http://httpredir.debian.org/debian experimental main
deb http://httpredir.debian.org/debian unstable main
sudo apt-get update
sudo apt-get install golang
nano ~/.bash_profile
export GOPATH=$HOME/go
source ~/.bash_profile
<- reload the profileenv | grep go
<- test it workedlsof
so Gondola can use it to determine when uploads are complete:
sudo apt-get install lsof
<- If lsof isn't already installed.sudo visudo -f /etc/sudoers.d/lsof
gondola ALL = (root) NOPASSWD: /usr/bin/lsof
sudo apt-get install ffmpeg
go get github.com/chrishulbert/gondola
nano ~/.gondola
root = "/media/gondola/KRYTEN/Gondola"
, customising the path to suit where your external drive mounts, save and quit.~/go/bin/gondola
<- it should say 'Watching for changes'. Do Ctrl+C to close.sudo nano /lib/systemd/system/gondola.service
Paste the following:
[Unit]
Description=Gondola media server
[Service]
PIDFile=/tmp/gondola.pid
User=gondola
Group=gondola
ExecStart=/home/gondola/go/bin/gondola
[Install]
WantedBy=multi-user.target
sudo systemctl enable gondola
<- make it run on boot
sudo systemctl start gondola
<- make it start now
systemctl status gondola
<- it should be 'active (running)'
sudo journalctl -u gondola
<- view its logs, should say 'watching for changes'
sudo apt-get install nginx
sudo nano /etc/nginx/sites-available/default
root /var/www/html;
and change line to: root /media/gondola/KRYTEN/Gondola;
- customise the path to suit where your hard drive mounts.sudo nano /etc/nginx/nginx.conf
user www-data;
and change to user gondola;
- this allows nginx to read your external HDD.sudo nginx -s reload
<- restart nginx.cat /var/log/nginx/error.log
New/TV
or New/Movies
, as per the file naming conventions described elsewhere here.sudo journalctl -u gondola | tail
.Gondola/Staging
folder while it works.top
to see that ffmpeg is hogging the CPU. Once it disappears from top, you'll know it's done.I don't really recommend using a CHIP, as I find it simply transcodes too slowly (13 hours to transcode 1 hour of movie). But if you don't mind, here you go:
Buy a chip from getchip.com
Flash it to the latest 'headless' version here. Headless leaves more resources available for Gondola.
Plug it into your TV and connect a USB keyboard (alternatively, connect to your computer via the USB port and connect to it via serial using eg screen - this can be less reliable IME than connecting to TV). Username and password default to 'chip'.
Change the hostname to 'gondola':
Set it up for your wifi, read more here.
sudo nmcli device wifi connect 'MyWifi' password 'MyPassword' ifname wlan0
Then you can ssh in from your mac's terminal:
ssh chip@gondola
Once you can SSH in, you can disconnect it from the TV/Mac (for serial-over-usb) and plug it in to just a plain USB wall power adapter.
Connecting to the Chip's USB input limits it to pulling 500mA, because the Chip's designers didn't want it to short-circuit people's laptops by pulling too much current. But this means it cannot reliably power an external USB flash drive. You have some options here:
sudo axp209 --no-limit sudo apt-get update sudo apt-get upgrade sudo systemctl enable no-limit sudo reboot
Whichever option above you choose, ensure you use a quality usb power supply (eg an apple/samsung genuine one). The cheap ones have uneven voltages and don't supply the promised amps, and your hardware will be flaky as a result (random crashes / data corruption). Also make sure you use a good quality USB cable, because the cheap ones don't have thick enough copper to deliver the necessary amps.
Connect a large capacity USB drive to your Chip that you're happy to erase and reformat, and we'll configure it next. Make sure you've addressed your power sourcing in the steps above before you connect a drive or you'll get brownouts.
Formatting steps:
sudo fdisk -l | grep Disk
/dev/sda
.sudo fdisk -l /dev/sda
(replace sda with whatever you discovered above) to see all the partitions currently on your USB drive. There's probably a FAT one.sudo fdisk /dev/sda
<- replace sda with whatever you discovered above.g
<- creates a gpt partition tablen
<- creates a new partition. Accept all the defaults by hitting return a few times.p
<- prints the details, it should look like this, note the device name:Disk /dev/sda: 57.8 GiB, 62087233536 bytes, 121264128 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: gpt Disk identifier: C7C3585E-CFC5-4A36-B61D-6B3B880F06DC
Device Start End Sectors Size Type /dev/sda1 2048 121264094 121262047 57.8G Linux filesystem
* `w` <- to write and exit
sudo mkfs.ext4 /dev/sda1
<- replacing sda1 with whatever is above.Mounting steps:
sudo mkdir /media/usb
<- creates a 'mount point'sudo chown chip /media/usb
<- allow chip to write to it.sudo chgrp chip /media/usb
sudo nano /etc/fstab
/dev/sda1 /media/usb ext4 defaults 0 0
<- replace /dev/sda1 with whatever is above.sudo mount -a
mount | grep usb
Install go:
sudo apt-get install git
No such file or directory: textflag.h
sudo nano /etc/apt/sources.list
deb http://httpredir.debian.org/debian experimental main
deb http://httpredir.debian.org/debian unstable main
sudo apt-get update
sudo apt-get install golang
nano ~/.bash_profile
export GOPATH=$HOME/go
source ~/.bash_profile
<- reload the profileenv | grep go
<- test it workedAllow password-less sudo access to lsof
so Gondola can use it to determine when uploads are complete:
sudo apt-get install lsof
<- If lsof isn't already installed.sudo visudo -f /etc/sudoers.d/lsof
chip ALL = (root) NOPASSWD: /usr/bin/lsof
Now install ffmpeg:
sudo apt-get install ffmpeg
Now we can install Gondola:
go get github.com/chrishulbert/gondola
nano ~/.gondola
root = "/media/usb/Gondola"
, save and quit.~/go/bin/gondola
<- it should say 'Watching for changes'. Do Ctrl+C to close.Make it run as a service:
sudo nano /lib/systemd/system/gondola.service
Paste the following:
[Unit] Description=Gondola media server
[Service] PIDFile=/tmp/gondola.pid User=chip Group=chip ExecStart=/home/chip/go/bin/gondola
[Install] WantedBy=multi-user.target
sudo systemctl enable gondola
<- make it run on boot
sudo systemctl start gondola
<- make it start now
systemctl status gondola
<- it should be 'active (running)'
sudo journalctl -u gondola
<- view its logs, should say 'watching for changes'
Install Nginx:
sudo apt-get install nginx
sudo nano /etc/nginx/sites-available/default
root /media/usb/Gondola
sudo nginx -s reload
<- restart nginx.Upload your first media:
New/TV
or New/Movies
, as per the file naming conventions described elsewhere here.sudo journalctl -u gondola | tail
.Gondola/Staging
folder while it works.top
to see that ffmpeg is hogging the CPU. Once it disappears from top, you'll know it's done.Good luck.
Gondola reduces 5.1 to stereo (with some trickery to ensure the sub channel isn't lost). This is to save space and for simpler playback on my stereo system.
If you upload a huge VOB, don't worry: gondola compresses to a reasonable size during the HLS conversion process.
Speed-wise, converting an average length (90min) 1080p movie takes 7 hours 30 mins on an HP Stream 11. On a GetCHIP, it takes around 20 hours.
sudo journalctl -u gondola
go get -u github.com/chrishulbert/gondola
sudo systemctl restart gondola
If you manually move the files around, you can force a metadata re-generation by restarting:
sudo systemctl restart gondola
To connect to the Chip via USB to your mac, do the following:
If screen fails because you quit without closing properly: Use fuser to find who has the port open and kill it: fuser /dev/cu.usbmodemFA133 returns: /dev/cu.usbmodemFA133: 95401 kill it: kill 95401
I've tried to make this work with Docker, however Gondola needs root access to detect if any other processes are writing to files in the New folder, so I don't recommend spending time investigating this unless you find a solution to that.
This product uses the TMDb API but is not endorsed or certified by TMDb.
Some icons from Icons8.com