{"id":13451991,"url":"https://github.com/devongovett/pi-christmas-lights","last_synced_at":"2025-03-16T07:32:32.307Z","repository":{"id":33871754,"uuid":"163138783","full_name":"devongovett/pi-christmas-lights","owner":"devongovett","description":"🎄 Sync Christmas lights to music with a Raspberry Pi and the Web Audio API","archived":false,"fork":false,"pushed_at":"2023-01-06T01:59:26.000Z","size":1848,"stargazers_count":75,"open_issues_count":14,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-27T05:51:12.944Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devongovett.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-26T05:12:23.000Z","updated_at":"2024-09-19T15:32:56.000Z","dependencies_parsed_at":"2023-01-15T03:05:17.876Z","dependency_job_id":null,"html_url":"https://github.com/devongovett/pi-christmas-lights","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devongovett%2Fpi-christmas-lights","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devongovett%2Fpi-christmas-lights/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devongovett%2Fpi-christmas-lights/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devongovett%2Fpi-christmas-lights/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devongovett","download_url":"https://codeload.github.com/devongovett/pi-christmas-lights/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243806052,"owners_count":20350775,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T07:01:09.404Z","updated_at":"2025-03-16T07:32:31.834Z","avatar_url":"https://github.com/devongovett.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# 🎄💡 pi-christmas-lights 🎄💡\n\nThis is the software for a project I built with my brother to sync our Christmas lights to music\nusing a Raspberry Pi and the Web Audio API.\n\n**[Watch the video!](https://twitter.com/devongovett/status/1077725421356101633)**\n\n![](https://media.giphy.com/media/3iBttTVcWRd7Ym5X4M/giphy.gif)\n\n## Hardware\n\nThe hardware uses a Raspberry Pi, 8 relays, some standard electrical outlets, and a bunch of wiring,\nall connected together in a wooden box under our front deck.\n\n\u003cimg src=\"https://pbs.twimg.com/media/Du-ZBB9XcAAyuk4.jpg:large\" width=\"400\"\u003e \u003cimg src=\"https://pbs.twimg.com/media/Du_0kl-W0AASkga.jpg\" width=\"400\"\u003e\n\nParts list:\n\n* [Raspberry Pi](https://www.raspberrypi.org)\n* [Relay](https://www.amazon.com/SainSmart-8-Channel-Duemilanove-MEGA2560-MEGA1280-x/dp/B006J4G45G)\n* [Male to female jumper wire](https://www.amazon.com/gp/product/B01EV70C78/ref=od_aui_detailpages01?ie=UTF8\u0026psc=1)\n* 4 outlet electrical box\n* 4 electrical outlets\n* Outlet cover\n* 14 guage electrical wire\n* Electrical wire nuts\n* Electrical tape\n* Wood and screws for the box\n* Lots of Christmas lights and extension cords 🎄🔌\n\n## Software\n\nThere are two parts to the software: the server, which runs on the Raspberry Pi, and the UI.\n\n### UI\n\nThe UI has two parts: an uploader, and a playback UI. Both are served from the Raspberry Pi\non our local network.\n\n#### Uploader\n\n![img_3364](https://media.giphy.com/media/67SXdxFjjEodEzA08A/giphy.gif)\n\nThe uploader uses the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)\nto perform audio analysis and generate the data needed to drive the light show. This happens in advance\nof the actual show so we don't need to do it in real time. The audio file is uploaded to the Pi and\nstored, along with computed light show timing data.\n\nAnalysis uses an [FFT](https://en.wikipedia.org/wiki/Fast_Fourier_transform) to analyze frequency\ndomain data from an audio file chosen to upload. The frequency spectrum is bucketed into 8 groups,\none for each light. This is similar to the bar graph display you might have seen on stereo equipment\nor other music visualizers. A rolling average is computed for each channel, and the lights turn on\nor off based on their distance from the mean. When the frequencies in this bucket are louder,\nthe lights turn on, and when they are soft, they turn off.\n\nThe analysis is done using an offline audio context, and the result can be uploaded and stored on the Pi.\nHowever, in order to make development and testing easier, the light show can be simulated in the browser\nusing virtual lights. This makes it much easier to tweak things without going outside in the freezing cold\nto watch the light show for real. 😜\n\n#### Playback\n\n\u003cimg src=\"https://user-images.githubusercontent.com/19409/50433089-0ef35e80-08a4-11e9-91b5-b8d50d5c3808.PNG\" width=\"200\"\u003e\n\nWhen it is time to play back a light show, a separate web page served from the Pi shows a list of songs\nwhich have been uploaded. Tapping on one of these downloads the audio to the user's phone, and triggers\nthe light show to begin playing on the Pi via an API. The Pi delays its playback by 1 second in order\nto avoid network lag, and tells the UI what time to start playing the audio on the phone. The audio is \nscheduled for that time and playback begins on both devices simultaneously.\n\n### Server\n\nThe Raspberry Pi has a webserver and an API, which is written using [NodeJS](https://nodejs.org) and\n[Express](http://expressjs.com). The lights are controlled using [rpio](https://npmjs.com/rpio) to\nturn on and off GPIO pins controlling the relays. The Pi stores uploaded audio files and light timing\ndata on its filesystem.\n\nTo play back a light show, the Pi reads the data file for light timing data stored for a song,\nwhich is a binary file that stores the light state for each frame. Usually there are 10 frames per second.\nSince there are only 8 lights, the light data is packed into bits to save space. Each frame, one\nbyte is read, and the lights are turned on or off according to the bits. In order to make the show\nmore interesting, the lights are rotated every 5 frames so that the frequency channels move around\nrather than staying fixed on one light.\n\n## Running the code\n\nTo run the client locally for development, run the following on your computer:\n\n```shell\n# Install deps\nyarn\n\n# Run UI server\nyarn watch\n```\n\nNow open http://localhost:1234/upload.html to try out the uploader. http://localhost:1234/index.html\nis the playback UI.\n\nTo run the server, run the following on your Raspberry Pi:\n\n```shell\n# Install deps\nyarn\n\n# Build UI\nyarn build\n\n# Run server\nyarn start\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevongovett%2Fpi-christmas-lights","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevongovett%2Fpi-christmas-lights","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevongovett%2Fpi-christmas-lights/lists"}