Skip to content

Instantly share code, notes, and snippets.

@lietu
Last active September 2, 2016 12:46
Show Gist options
  • Save lietu/f49db5b39a3f17d247f437e8be8ad42e to your computer and use it in GitHub Desktop.
Save lietu/f49db5b39a3f17d247f437e8be8ad42e to your computer and use it in GitHub Desktop.
Making living with OBS Studio easier
<html><head><!--
OBS Studio video playback tool. To get video to play automatically, and get audio to stream AND desktop so you can hear it as well.
1. Edit the "Configuration" -section below, save this file in the same directory as your video
2. Make sure you have the Browser Source installed in your OBS Studio
3. Add a new BrowserSource -source to your scene of choice
4. Choose "Local File" and point it to this file
5. Set width and height to your streaming resolution
6. Check "Shutdown when not active"
Example for 720p stream: http://imgur.com/kkodlbv
--><style>* { background: #000; margin: 0; padding: 0; width: 100%; height: 100%; }</style>
</head><body><video loop id="video"></video><script>
// Configuration
// Volume is a fraction 0-1, so 0.2 = 20%
var volume = 0.2;
// Full and correct filename to the video to play, should be in the same directory
var videoPath = "intro_v3.mp4";
/**********************************\
* BLACK MAGIC BELOW - DO NOT TOUCH *
\**********************************/
function setup() {
var video = document.getElementById("video");
var source = document.createElement("source");
source.src = videoPath;
video.appendChild(source);
video.volume = volume;
video.play();
}
setup();
</script></body></html>
<!DOCTYPE HTML><html><head>
<!--
Example OBS studio effect for use with Browser Source using Canvas and Audio support to render fireworks, show a welcome screen, and play sounds.
To actually use this example you will need to provide your own audio files and images.
How it looks like for me: https://youtu.be/lyzBVDPNEFA
Setup:
- Pick your own audio files (.ogg is a good format) and update the "launch" and "explosion" file lists.
- Pick your own welcome image, and update the <img> -tag to point to the correct file (PNG format should likely be used, as it supports transparency).
- Update launchVolume and explosionVolume below
- Add a BrowserSource to your scenes in OBS Studio
- Configure it using a "Local file", pointing it to this file (make sure the audio + image are in the same folder)
- Set width & height to match your streaming resolution (e.g. 1280x720 for 720p streams)
- Enable "Shutdown when not active" -checkbox
Usage:
- Keep the BrowserSource hidden by default
- When you want to show the effect enable it (you can hotkey that)
- Hide it after the effects have stopped playing so you can replay it next time you need it
-->
<style type="text/css">
body, html, canvas, img {
width: 100%; height: 100%; overflow: hidden;
margin: 0; padding: 0;
background: transparent;
}
canvas, img {
position: absolute; top: 0; left: 0;
}
@keyframes fadeAnimation {
0% { opacity: 0; }
20% { opacity: 1; }
80% { opacity: 1; }
100% { opacity: 0; }
}
.fade {
opacity: 0;
animation: fadeAnimation 5s 1;
}
</style></head><body>
<!-- Update this image src attribute, or remove the <img> tag completely -->
<img class="fade" src="raiders.png">
<canvas id="canvas"></canvas>
<script type="text/javascript">
/***************\
* CONFIGURATION *
\***************/
var audio = {
launch: ["launch1.ogg", "launch2.ogg", "launch3.ogg", "launch4.ogg", "launch5.ogg"],
explosion: ["explode1.ogg", "explode2.ogg", "explode3.ogg"]
};
// After how many milliseconds should we stop launching rockets
var launchFor = 3000;
// How many milliseconds between launching rockets
var launchInterval = 500;
// Volume is a fraction between 0 and 1, i.e. 0.1 = 10%
var launchVolume = 0.05;
var explosionVolume = 0.1;
/*******************\
* *
* BLACK MAGIC BELOW *
* *
* DO NOT TOUCH! *
* *
\*******************/
// Fireworks code based on http://jsfiddle.net/dtrooper/AceJJ/
function randbetween(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function choose(list) {
return list[Math.floor(Math.random() * list.length)];
}
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight,
canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
particles = [],
rockets = [],
MAX_PARTICLES = 2000,
colorCode = 0;
function playSound(filename, volume) {
var audio = new Audio();
audio.src = filename;
audio.volume = volume;
audio.play();
}
function init() {
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
var launchUntil = Date.now() + launchFor;
var launcher = setInterval(function() {
launch();
if (Date.now() > launchUntil) {
clearInterval(launcher);
}
}, launchInterval);
setInterval(loop, 1000 / 50);
}
function launch() {
launchFrom(randbetween(100, SCREEN_WIDTH - 100));
}
function launchFrom(x) {
if (rockets.length < 10) {
var rocket = new Rocket(x);
rocket.explosionColor = Math.floor(Math.random() * 360 / 10) * 10;
rocket.vel.y = -12 + (Math.random() * -3 - 4);
rocket.vel.x = Math.random() * 6 - 3;
rocket.size = 12;
rocket.shrink = 0.999;
rocket.gravity = 0.01;
rockets.push(rocket);
playSound(choose(audio.launch), launchVolume);
}
}
function fade() {
context.save();
var w = canvas.width;
var h = canvas.height;
context.globalAlpha = 0.1;
context.globalCompositeOperation = 'destination-out';
context.fillStyle = '#FFF';
context.fillRect(0, 0,w, h);
context.restore();
}
function updateScreenSize() {
if (SCREEN_WIDTH != window.innerWidth) {
canvas.width = SCREEN_WIDTH = window.innerWidth;
}
if (SCREEN_HEIGHT != window.innerHeight) {
canvas.height = SCREEN_HEIGHT = window.innerHeight;
}
}
function loop() {
updateScreenSize();
fade();
var existingRockets = [];
for (var i = 0; i < rockets.length; i++) {
rockets[i].update();
rockets[i].render(context);
var randomChance = rockets[i].pos.y < (SCREEN_HEIGHT * 2 / 3) ? (Math.random() * 100 <= 1) : false;
if (rockets[i].pos.y < SCREEN_HEIGHT / 5 || rockets[i].vel.y >= 0 || randomChance) {
rockets[i].explode();
} else {
existingRockets.push(rockets[i]);
}
}
rockets = existingRockets;
var existingParticles = [];
for (var i = 0; i < particles.length; i++) {
particles[i].update();
if (particles[i].exists()) {
particles[i].render(context);
existingParticles.push(particles[i]);
}
}
particles = existingParticles;
while (particles.length > MAX_PARTICLES) {
particles.shift();
}
}
function Particle(pos) {
this.pos = {
x: pos ? pos.x : 0,
y: pos ? pos.y : 0
};
this.vel = {
x: 0,
y: 0
};
this.shrink = .97;
this.size = 2;
this.resistance = 1;
this.gravity = 0;
this.flick = false;
this.alpha = 1;
this.fade = 0;
this.color = 0;
}
Particle.prototype.update = function () {
// apply resistance
this.vel.x *= this.resistance;
this.vel.y *= this.resistance;
// gravity down
this.vel.y += this.gravity;
// update position based on speed
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
// shrink
this.size *= this.shrink;
// fade out
this.alpha -= this.fade;
};
Particle.prototype.render = function (c) {
if (!this.exists()) {
return;
}
c.save();
c.globalCompositeOperation = 'lighter';
var x = this.pos.x,
y = this.pos.y,
r = this.size / 2;
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")");
gradient.addColorStop(0.8, "hsla(" + this.color + ", 100%, 50%, " + this.alpha + ")");
gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0.1)");
c.fillStyle = gradient;
c.beginPath();
c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size : this.size, 0, Math.PI * 2, true);
c.closePath();
c.fill();
c.restore();
};
Particle.prototype.exists = function () {
return this.alpha >= 0.1 && this.size >= 1;
};
function Rocket(x) {
Particle.apply(this, [{
x: x,
y: SCREEN_HEIGHT
}]);
this.explosionColor = 0;
}
Rocket.prototype = new Particle();
Rocket.prototype.constructor = Rocket;
Rocket.prototype.explode = function () {
var count = Math.random() * 10 + 80;
for (var i = 0; i < count; i++) {
var particle = new Particle(this.pos);
var angle = Math.random() * Math.PI * 2;
// emulate 3D effect by using cosine and put more particles in the middle
var speed = Math.cos(Math.random() * Math.PI / 2) * 15;
particle.vel.x = Math.cos(angle) * speed;
particle.vel.y = Math.sin(angle) * speed;
particle.size = 12;
particle.gravity = 0.2;
particle.resistance = 0.92;
particle.shrink = Math.random() * 0.05 + 0.94;
particle.flick = true;
particle.color = this.explosionColor;
particles.push(particle);
}
playSound(choose(audio.explosion), explosionVolume);
};
Rocket.prototype.render = function (c) {
if (!this.exists()) {
return;
}
c.save();
c.globalCompositeOperation = 'lighter';
var x = this.pos.x,
y = this.pos.y,
r = this.size / 2;
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
gradient.addColorStop(0.1, "rgba(255, 255, 255 ," + this.alpha + ")");
gradient.addColorStop(1, "rgba(0, 0, 0, " + this.alpha + ")");
c.fillStyle = gradient;
c.beginPath();
c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size / 2 + this.size / 2 : this.size, 0, Math.PI * 2, true);
c.closePath();
c.fill();
c.restore();
};
init();
</script></body></html>
@lietu
Copy link
Author

lietu commented Sep 1, 2016

If you don't want it to loop just remove the loop -attribute from the <video> -tag on line 14. https://gist.github.com/lietu/f49db5b39a3f17d247f437e8be8ad42e#file-obs_studio_video_playback-html-L14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment