Calculator Tools Calculator Tools

YTPMV Scan - Ultimate Audio Visual Sequencer

Sep 6, 2026

About this app

Create chaotic and rhythmic YouTube Poop Music Videos with this interactive scanline sequencer. Upload samples, adjust BPM, and remix live!

YTPMV Scan - Ultimate Audio Visual Sequencer YTPMV SCAN Tap anywhere to initialize Poop Engine... START SCAN CLEAR GRID TEMPO: 130 BPM RANDOMIZE GLITCH UI LOAD BG Add Poop Visuals Instructions: Click/Tap cells to toggle a sound trigger. Each row corresponds to a different classic poop sound. Upload your own image to act as the "source" for your YTPMV. Adjust the tempo for hyper-fast or slow-motion Poops. © 2024 YTPMV Scanner Visual Sequencer - Created for the WebPoopers.

Put this on your site

Source

                    <html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">

<title>YTPMV Scan - Ultimate Audio Visual Sequencer</title>
<meta name="description" content="Create chaotic and rhythmic YouTube Poop Music Videos with this interactive scanline sequencer. Upload samples, adjust BPM, and remix live!">
<meta name="keywords" content="YTPMV, sequencer, music maker, web audio, scanline, rhythm game, visualizer, audio visual">

<!-- Libraries -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" crossorigin="anonymous">

<script type="text/javascript">
try {
// Core Audio Engine
let audioCtx;
let samples = {};
let grid = [];
const ROWS = 8;
const COLS = 16;
let bpm = 130;
let isPlaying = false;
let currentStep = 0;
let nextTickTime = 0;
let lookAhead = 25.0; // ms
let scheduleAheadTime = 0.1; // seconds
let timerID;

// Visual Constants
const COLORS = [
'#ff00ff', '#00ffff', '#ffff00', '#ff0000',
'#00ff00', '#ff8800', '#8800ff', '#ffffff'
];

// Default Sound Links (Creative Commons / Placeholder friendly)
const DEFAULT_SOUNDS = [
{ id: 'bass', url: 'https://actions.google.com/sounds/v1/science_fiction/low_vibrating_hum.ogg' },
{ id: 'snare', url: 'https://actions.google.com/sounds/v1/drums/snare_drum.ogg' },
{ id: 'kick', url: 'https://actions.google.com/sounds/v1/drums/conga_hit.ogg' },
{ id: 'clap', url: 'https://actions.google.com/sounds/v1/foley/beating_on_books.ogg' },
{ id: 'ping', url: 'https://actions.google.com/sounds/v1/alarms/digital_watch_alarm_long.ogg' },
{ id: 'laser', url: 'https://actions.google.com/sounds/v1/science_fiction/sci_fi_door.ogg' },
{ id: 'glitch', url: 'https://actions.google.com/sounds/v1/foley/plastic_crumple.ogg' },
{ id: 'vox', url: 'https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg' }
];

async function loadSample(id, url) {
try {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
samples[id] = audioBuffer;
return true;
} catch (e) {
console.error("Failed to load sample:", id, e);
return false;
}
}

function playSample(id, time) {
if (!samples[id]) return;
const source = audioCtx.createBufferSource();
source.buffer = samples[id];

const gainNode = audioCtx.createGain();
gainNode.gain.setValueAtTime(0.7, time);
gainNode.gain.exponentialRampToValueAtTime(0.01, time + 0.5);

source.connect(gainNode);
gainNode.connect(audioCtx.destination);
source.start(time);
}

function initGrid() {
grid = [];
for (let r = 0; r < ROWS; r++) {
grid[r] = new Array(COLS).fill(false);
}
}

function nextStep() {
const secondsPerBeat = 60.0 / bpm / 4; // 16th notes
nextTickTime += secondsPerBeat;
currentStep = (currentStep + 1) % COLS;
}

function scheduler() {
while (nextTickTime < audioCtx.currentTime + scheduleAheadTime) {
scheduleStep(currentStep, nextTickTime);
nextStep();
}
timerID = setTimeout(scheduler, lookAhead);
}

function scheduleStep(step, time) {
for (let r = 0; r < ROWS; r++) {
if (grid[r][step]) {
playSample(`s${r}`, time);
// Visual feedback triggers handled via step class update
}
}

// UI sync
requestAnimationFrame(() => {
$('.cell').removeClass('active-col');
$(`.cell[data-col="${step}"]`).addClass('active-col');
if (grid.some((row, rIdx) => grid[rIdx][step])) {
$(`.cell[data-col="${step}"]`).addClass('impact');
setTimeout(() => {
$(`.cell[data-col="${step}"]`).removeClass('impact');
}, 100);
}
});
}

function togglePlay() {
if (!audioCtx) {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
initDefaultSamples();
}

if (audioCtx.state === 'suspended') {
audioCtx.resume();
}

isPlaying = !isPlaying;
if (isPlaying) {
nextTickTime = audioCtx.currentTime;
scheduler();
$('#play-btn').html('<i class="fas fa-pause"></i> PAUSE').addClass('btn-danger').removeClass('btn-success');
} else {
clearTimeout(timerID);
$('#play-btn').html('<i class="fas fa-play"></i> START SCAN').addClass('btn-success').removeClass('btn-danger');
$('.cell').removeClass('active-col');
}
}

async function initDefaultSamples() {
$('#status').text("Loading Core Audio Samples...");
for (let i = 0; i < ROWS; i++) {
await loadSample(`s${i}`, DEFAULT_SOUNDS[i % DEFAULT_SOUNDS.length].url);
}
$('#status').text("Ready to Poop! Tap cells to sequence.");
setTimeout(() => $('#status').fadeOut(), 3000);
}

function renderGrid() {
const container = $('#grid-container');
container.empty();
for (let r = 0; r < ROWS; r++) {
const rowDiv = $('<div class="grid-row"></div>');
for (let c = 0; c < COLS; c++) {
const cell = $(`<div class="cell" data-row="${r}" data-col="${c}"></div>`);
cell.css('--cell-color', COLORS[r]);
if (grid[r][c]) cell.addClass('selected');

cell.on('click touchstart', function(e) {
e.preventDefault();
grid[r][c] = !grid[r][c];
$(this).toggleClass('selected');
if (grid[r][c] && audioCtx) playSample(`s${r}`, audioCtx.currentTime);
});
rowDiv.append(cell);
}
container.append(rowDiv);
}
}

document.addEventListener("DOMContentLoaded", function() {
initGrid();
renderGrid();

$('#play-btn').on('click', togglePlay);

$('#bpm-slider').on('input', function() {
bpm = $(this).val();
$('#bpm-val').text(bpm);
});

$('#clear-btn').on('click', function() {
initGrid();
$('.cell').removeClass('selected');
});

$('#random-btn').on('click', function() {
for (let r = 0; r < ROWS; r++) {
for (let c = 0; c < COLS; c++) {
grid[r][c] = Math.random() > 0.85;
}
}
renderGrid();
});

$('#glitch-btn').on('click', function() {
$('body').addClass('glitch-effect');
setTimeout(() => $('body').removeClass('glitch-effect'), 500);
});

// Add image background feature
$('#img-upload').on('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(event) {
$('#grid-container').css('background-image', `url(${event.target.result})`);
$('#grid-container').css('background-size', 'cover');
$('#grid-container').css('background-position', 'center');
};
reader.readAsDataURL(file);
}
});
});

} catch (error) {
console.error("YTPMV Global Error:", error);
throw error;
}
</script>

<style>
:root {
--bg-color: #0d0221;
--accent-color: #00ffcc;
--panel-color: #1a0b3c;
--text-color: #ffffff;
--neon-pink: #ff00ff;
--neon-blue: #00ffff;
}

body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-image:
linear-gradient(rgba(13, 2, 33, 0.8), rgba(13, 2, 33, 0.8)),
url('https://www.transparenttextures.com/patterns/carbon-fibre.png');
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
overflow-x: hidden;
}

#main-container {
width: 100%;
max-width: 900px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 20px;
margin-top: env(safe-area-inset-top);
}

header {
text-align: center;
margin-bottom: 10px;
}

h1 {
font-size: 2.5rem;
font-weight: 900;
text-transform: uppercase;
letter-spacing: 5px;
margin: 0;
background: linear-gradient(to right, var(--neon-pink), var(--neon-blue), var(--accent-color));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 20px rgba(0, 255, 204, 0.3);
}

#status {
color: var(--accent-color);
font-size: 0.9rem;
margin-top: 5px;
min-height: 1.5em;
}

/* The Sequencer Grid */
#grid-container {
position: relative;
width: 100%;
aspect-ratio: 16 / 8;
background-color: rgba(0,0,0,0.5);
border: 4px solid var(--panel-color);
box-shadow: 0 0 30px rgba(0,0,0,0.5), inset 0 0 100px rgba(255,0,255,0.1);
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
}

.grid-row {
display: flex;
flex: 1;
width: 100%;
}

.cell {
flex: 1;
border: 1px solid rgba(255,255,255,0.05);
cursor: pointer;
transition: all 0.1s ease;
position: relative;
background-clip: content-box;
}

.cell.selected {
background-color: var(--cell-color);
box-shadow: inset 0 0 15px rgba(255,255,255,0.6);
animation: flicker 2s infinite;
}

.cell.active-col {
border-left: 2px solid #fff;
border-right: 2px solid #fff;
z-index: 10;
background-color: rgba(255,255,255,0.1);
}

.cell.active-col.impact {
animation: scanImpact 0.1s ease-out;
}

@keyframes scanImpact {
0% { background-color: rgba(255,255,255,0.5); transform: scale(1.1); }
100% { background-color: transparent; transform: scale(1); }
}

@keyframes flicker {
0%, 100% { opacity: 1; }
50% { opacity: 0.8; }
}

/* Controls Panel */
.controls-panel {
background: var(--panel-color);
padding: 20px;
border-radius: 15px;
box-shadow: 0 10px 20px rgba(0,0,0,0.3);
display: flex;
flex-wrap: wrap;
gap: 15px;
justify-content: space-around;
align-items: center;
border: 2px solid rgba(255,255,255,0.1);
}

.control-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}

.btn-cyber {
padding: 12px 24px;
border: none;
border-radius: 8px;
font-weight: bold;
text-transform: uppercase;
transition: all 0.2s;
min-width: 120px;
box-shadow: 0 4px 0 rgba(0,0,0,0.4);
}

.btn-cyber:active {
transform: translateY(3px);
box-shadow: 0 1px 0 rgba(0,0,0,0.4);
}

input[type=range] {
-webkit-appearance: none;
width: 150px;
height: 10px;
background: rgba(0,0,0,0.5);
border-radius: 5px;
outline: none;
}

input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
background: var(--accent-color);
cursor: pointer;
border-radius: 50%;
border: 3px solid #fff;
}

.footer-info {
font-size: 0.8rem;
opacity: 0.6;
text-align: center;
margin-top: 20px;
}

/* Effects */
.glitch-effect {
animation: shake 0.2s cubic-bezier(.36,.07,.19,.97) both;
transform: translate3d(0, 0, 0);
}

@keyframes shake {
10%, 90% { transform: translate3d(-2px, 0, 0); filter: hue-rotate(90deg) contrast(150%); }
20%, 80% { transform: translate3d(4px, 0, 0); }
30%, 50%, 70% { transform: translate3d(-8px, 0, 0); }
40%, 60% { transform: translate3d(8px, 0, 0); }
}

/* Mobile tweaks */
@media (max-width: 600px) {
h1 { font-size: 1.5rem; letter-spacing: 2px; }
.controls-panel { padding: 10px; }
.btn-cyber { width: 100%; min-width: unset; }
#grid-container { border-width: 2px; }
}
</style>
</head>
<body>
<div id="main-container">
<header>
<h1><i class="fas fa-barcode"></i> YTPMV SCAN</h1>
<div id="status">Tap anywhere to initialize Poop Engine...</div>
</header>

<div id="grid-container">
<!-- Grid Cells Generated by JS -->
</div>

<div class="controls-panel">
<div class="control-group">
<button id="play-btn" class="btn btn-success btn-lg btn-cyber">
<i class="fas fa-play"></i> START SCAN
</button>
<button id="clear-btn" class="btn btn-outline-light btn-sm mt-1">
CLEAR GRID
</button>
</div>

<div class="control-group">
<label>TEMPO: <span id="bpm-val">130</span> BPM</label>
<input type="range" id="bpm-slider" min="60" max="220" value="130">
</div>

<div class="control-group">
<button id="random-btn" class="btn btn-primary btn-cyber">
RANDOMIZE
</button>
<button id="glitch-btn" class="btn btn-warning btn-cyber mt-2">
GLITCH UI
</button>
</div>

<div class="control-group">
<label for="img-upload" class="btn btn-info btn-cyber">
<i class="fas fa-image"></i> LOAD BG
</label>
<input type="file" id="img-upload" hidden accept="image/*">
<p class="mb-0 small opacity-50">Add Poop Visuals</p>
</div>
</div>

<div class="card bg-dark text-light border-secondary mt-3">
<div class="card-body py-2 px-3">
<h6 class="card-title mb-1"><i class="fas fa-info-circle"></i> Instructions:</h6>
<ul class="mb-0 small" style="padding-left: 20px;">
<li>Click/Tap cells to toggle a sound trigger.</li>
<li>Each row corresponds to a different classic poop sound.</li>
<li>Upload your own image to act as the "source" for your YTPMV.</li>
<li>Adjust the tempo for hyper-fast or slow-motion Poops.</li>
</ul>
</div>
</div>

<div class="footer-info">
&copy; 2024 YTPMV Scanner Visual Sequencer - Created for the WebPoopers.
</div>
</div>

<script>
// Audio context start guard
$('body').on('click touchstart', function() {
if (audioCtx && audioCtx.state === 'suspended') {
audioCtx.resume();
}
});
</script>
</body>
</html>