Skip to content

Instantly share code, notes, and snippets.

View mariotacke's full-sized avatar
💻
Specializing in the outrageous.

Mario Tacke mariotacke

💻
Specializing in the outrageous.
View GitHub Profile
@mariotacke
mariotacke / README.md
Last active April 4, 2024 14:33
Spotify AutoHotkey Script

Spotify AutoHotkey Script

This script makes use of the Numpad to control media players and volume on your system.

Usage

  • Install AutoHotkey
  • Right-click .ahk script
  • Compile Script
  • Start executable

Hotkeys

@mariotacke
mariotacke / README.md
Created March 7, 2017 04:36
Default nginx log format (combined) and grok pattern
@mariotacke
mariotacke / README.md
Last active July 5, 2021 07:44
Gulp replace to invalidate cache

Gulp replace to invalidate cache

This demo replaces the string @@VERSION with the current unix timestamp when building with gulp. @@VERSION is a query parameter to bundle.js. To avoid caching bundle.js, we add the timestamp to it during each build.

Usage

npm install
npm run build
@mariotacke
mariotacke / teamcity-agent
Last active February 23, 2021 14:57
/etc/init.d/teamcity-agent auto start script for TeamCity Agents
#!/bin/sh
### BEGIN INIT INFO
# Provides: TeamCity Build Agent
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start build agent daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO
const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%&()/\\+<>';
const randomCharacter = charset[Math.floor(Math.random() * charset.length)];
outputContext.fillStyle = `rgb(${r},${g},${b})`;
outputContext.fillText(randomCharacter, x, y);
for (let y = 0; y < height; y += fontHeight) {
for (let x = 0; x < width; x += fontWidth) {
const frameSection = hiddenContext.getImageData(x, y, fontWidth, fontHeight);
const { r, g, b } = getAverageRGB(frameSection);
outputContext.fillStyle = `rgb(${r},${g},${b})`;
outputContext.fillText('@', x, y);
}
}
const getAverageRGB = (frame) => {
const length = frame.data.length / 4;
let r = 0;
let g = 0;
let b = 0;
for (let i = 0; i < length; i++) {
r += frame.data[i * 4 + 0];
g += frame.data[i * 4 + 1];
const fontHeight = 12;
if (width && height) {
// canvas setup removed for brevity
hiddenContext.drawImage(video, 0, 0, width, height);
outputContext.textBaseline = 'top';
outputContext.font = `${fontHeight}px Consolas`;
const text = outputContext.measureText('@');
const video = document.querySelector('#camera-stream');
const hiddenCanvas = document.querySelector('#hidden-canvas');
const outputCanvas = document.querySelector('#output-canvas');
const hiddenContext = hiddenCanvas.getContext('2d');
const outputContext = outputCanvas.getContext('2d');
const processFrame = () => {
const { videoWidth: width, videoHeight: height } = video;
if (width && height) {
const constraints = {
video: {
width: 512,
height: 512,
},
};
navigator.getUserMedia(constraints, function (stream) {
video.srcObject = stream;
video.play();