Public
Edited
Aug 9, 2023
Insert cell
Insert cell
Insert cell
// viewof audioHTML = html`
// <audio/mp3
// controls
// crossorigin="anonymous"
// id="audio"
// src="${audioUrl}"
// autoplay
// >
// </audio>
// `
Insert cell
// displayDistortedImage(scrub_input, reverseMap)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
myCanvas = html`<canvas id="my-canvas" width="480" height="270"></canvas>`
Insert cell
myVideo = html`<video id="my-video" controls="true" width="480" height="270" crossorigin="anonymous">
<source src="http://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm" type="video/webm">
<source src="http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v" type="video/mp4">
</video>`
Insert cell
processor = ({
timerCallback: function() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
var self = this;
setTimeout(function() {
self.timerCallback();
}, 16); // roughly 60 frames per second
},

doLoad: function() {
this.video = myVideo;
this.c1 = myCanvas;
this.ctx1 = this.c1.getContext("2d");
var self = this;

this.video.addEventListener(
"play",
function() {
self.width = self.video.width;
self.height = self.video.height;
self.timerCallback();
},
false
);
},

// computeFrame: function() {
// this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
// var input = this.ctx1.getImageData(0, 0, this.width, this.height);
// var output = this.cctx1.getImageData(0, 0, this.width, this.height);

// distortPixels(input, output, this.width, this.height, reverseMap);
// var frame = this.ctx1.getImageData(0, 0, this.width, this.height);
// var l = frame.data.length / 4;


// for (var i = 0; i < l; i++) {
// var grey =
// (frame.data[i * 4 + 0] +
// frame.data[i * 4 + 1] +
// frame.data[i * 4 + 2]) /
// 3;

// frame.data[i * 4 + 0] = grey;
// frame.data[i * 4 + 1] = grey;
// frame.data[i * 4 + 2] = grey;
// }
// this.ctx1.putImageData(frame, 0, 0);

// return;
// }

computeFrame: function() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
var frame = this.ctx1.getImageData(0, 0, this.width, this.height);
var l = frame.data.length / 4;

for (var i = 0; i < l; i++) {
var grey =
(frame.data[i * 4 + 0] +
frame.data[i * 4 + 1] +
frame.data[i * 4 + 2]) /
3;

frame.data[i * 4 + 0] = grey;
frame.data[i * 4 + 1] = grey;
frame.data[i * 4 + 2] = grey;
}
this.ctx1.putImageData(frame, 0, 0);

return;
}
})
Insert cell
processor.doLoad()
Insert cell
// // const framesMap = eachFrame
// framesMap = eachFrame(src, framerate, -1, 0, {
// crossOrigin: 'anonymous',
// debug: true
// })
Insert cell
// src = "https://raw.githubusercontent.com/mdn/interactive-examples/master/live-examples/media/cc0-videos/flower.mp4"
// src = "https://raw.githubusercontent.com/mdn/dom-examples/master/canvas/chroma-keying/media/video.mp4"
Insert cell
// viewof frameIdx = Scrubber(framesMap.keys(), {
// loop: false,
// delay: 1000 / framerate,
// autoplay: false
// })
Insert cell
// framesMap.get(frameIdx)
Insert cell
// framerate = 30
Insert cell
import {eachFrame} from '@theo-jaunet/from-video-to-frames'
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// audioUrl = audioUrls[episode_selection[0]["Episode"]]
Insert cell
// audioUrls = ({
// Family: FileAttachment("Off the Air - S11E01 - Family [WEBDL-1080p]@2.mp3").url() ,
// Nightmares: FileAttachment("Off the Air - S02E03 - Nightmares [WEBDL-1080p]@1.mp3").url(),
// Dreams: FileAttachment("Off the Air - S10E02 - Dreams [WEBDL-1080p].mp3").url(),
// Coping: FileAttachment("Off the Air - S10E01 - Coping [WEBDL-1080p].mp3").url(),
// Love: FileAttachment("Off the Air - S08E02 - Love [WEBDL-1080p].mp3").url(),
// Conflict: FileAttachment("Off the Air - S05E02 - Conflict [WEBDL-1080p].mp3").url(),
// Paradise: FileAttachment("Off the Air - S07E03 - Paradise [WEBDL-1080p].mp3").url(),
// Bliss: FileAttachment("Off the Air - S12E03 - Bliss [WEBDL-1080p].mp3").url(),
// Death: FileAttachment("Off the Air - S04E03 - Death [WEBDL-1080p].mp3").url(),
// })
Insert cell
// analyzer = initialize(audioUrl);
Insert cell
function initialize() {
if (!audioUrl) {
return null;
}
const audioContext = new AudioContext()
invalidation.then(() => audioContext.close());
let htmlAudioElement = document.querySelector('audio');
const source = audioContext.createMediaElementSource(htmlAudioElement);
source.connect(audioContext.destination);

const analyzer = meyda.createMeydaAnalyzer({
"audioContext": audioContext,
"source": source,
"bufferSize": 512,
"windowingFunction": 'hanning',
"featureExtractors": ["energy", "spectralFlatness", "spectralCentroid", "spectralSpread"],
});

analyzer.start();
return analyzer;
}

Insert cell
// function initialize() {
// if (!audioUrl) {
// return null;
// }
// const audioContext = new AudioContext()
// invalidation.then(() => audioContext.close());
// let htmlAudioElement = document.querySelector('audio');
// const source = audioContext.createMediaElementSource(htmlAudioElement);
// source.connect(audioContext.destination);

// const analyzer = meyda.createMeydaAnalyzer({
// "audioContext": audioContext,
// "source": source,
// "bufferSize": 512,
// "windowingFunction": 'hanning',
// "featureExtractors": ["energy", "spectralFlatness", "spectralCentroid", "spectralSpread"],
// });

// analyzer.start();
// return analyzer;
// }

Insert cell
// audioElement = {
// await analyzer
// return document.getElementById('audio');
// }
Insert cell
Insert cell
Insert cell
Insert cell
// img_choice = {
// await audioElement.currentTime > 0
// yield Math.floor((audioElement.currentTime+.1)/5)
// while (true) yield Promises.delay((5000 - 1000*(Math.floor(audioElement.currentTime)) % 5000), 1+Math.floor((audioElement.currentTime)/5));
// }



// // viewof img_choice = Math.floor(audioContext.currentTime/5)

// // viewof img_choice = {
// // const element = htl.html`<div>I am a silly view!</div>`;
// // element.value = Math.floor(audioContext.currentTime/5);
// // return element;
// // }

// // viewof img_choice = Range([1, githubImgs2.length-1], {
// // label: "Frame #",
// // step: 1,
// // value: 121
// // })
Insert cell
// scrub_input = {
// let img = vid_urls[img_choice]
// let ctx = DOM.canvas(img.naturalWidth, img.naturalHeight).getContext("2d");
// ctx.drawImage(img, 0, 0);

// return {
// data: ctx.getImageData(0, 0, img.naturalWidth, img.naturalHeight),
// width: img.naturalWidth,
// height: img.naturalHeight
// };
// }

Insert cell
// cur_colors = {
// let cur = episode_selection[img_choice]
// // return cur["Colour3"]
// return new Set([color_mapping[cur["Colour1"]], color_mapping[cur["Colour2"]], color_mapping[cur["Colour3"]]])
// }
Insert cell
// function displayDistortedImage(input, reverseMap) {
// const ctx = DOM.context2d(input.width, input.height, 1);
// const outputPixels = ctx.getImageData(0, 0, input.width, input.height);
// distortPixels(
// input.data,
// outputPixels,
// input.width,
// input.height,
// reverseMap
// );
// if (color_fluct != 0 | color_base != 0) {
// let cur = episode_selection[img_choice]
// let interpolator
// if (colorMap == "Color Pallette") {
// interpolator = d3.interpolateRgb(...cur_colors);
// } else {
// interpolator = d3[`interpolate${colorMap}`];
// }
// const LUT = Array.from({ length: 256 }, (_, i) => d3.color(interpolator(i / 255)));

// let w = color_fluct*spectralSpread/50 + color_base*spectralCentroid/50
// for(let i=0; i<outputPixels.data.length; i+=4) {
// const color=LUT[outputPixels.data[i]];
// outputPixels.data[i] = (1-w)*outputPixels.data[i] + w*color.r;
// outputPixels.data[i+1] = (1-w)*outputPixels.data[i+1] + w*color.g;
// outputPixels.data[i+2] = (1-w)*outputPixels.data[i+2] + w*color.b;
// }
// }
// ctx.putImageData(outputPixels, 0, 0);
// ctx.canvas.style.maxWidth = "100%";
// return html`${ctx.canvas}`;
// }

Insert cell
// // modification of https://observablehq.com/@kerryrodden/image-distortion-with-perlin-noise
// function getShiftedPixelIndex(x, y, width, height) {
// let scale = flatnessDistort*scaling/10
// let amount = energy * amount_scale
// let offset1a = offset1 * oscillation * multiplier + offset1
// let offset2a = offset2 * oscillation * multiplier + offset2
// // let shift1a = movement * oscillation * multiplier
// const shift = {
// x: amount * noise(scale * x, scale * y),
// y: amount * noise(offset1a + scale * x, offset2a + scale * y)
// };
// const newX = clamp(Math.round(x + shift.x), 0, width - 1);
// const newY = clamp(Math.round(y + shift.y), 0, height - 1);
// return getPixelIndex(newX, newY, width);
// }
Insert cell
// function distortPixels(inputPixels, outputPixels, width, height, reverseMap) {
// for (let x = 0; x < width; x++) {
// for (let y = 0; y < height; y++) {
// const inputIndex = reverseMap
// ? getShiftedPixelIndex(x, y, width, height)
// : getPixelIndex(x, y, width);
// const outputIndex = reverseMap
// ? getPixelIndex(x, y, width)
// : getShiftedPixelIndex(x, y, width, height);
// for (let i = 0; i < 4; i++) {
// outputPixels.data[outputIndex + i] = inputPixels.data[inputIndex + i];
// }
// }
// }
// }
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more