This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createServer } from 'https'; | |
import { generate } from 'selfsigned'; | |
const certAttrs = [{ name: 'commonName', value: 'www.compulim.com' }]; | |
const certOptions = { | |
// Options copied from default values | |
// https://github.com/jfromaniello/selfsigned/blob/master/index.js#L85 | |
extensions: [ | |
{ | |
name: 'subjectAltName', |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# This script will act as a RTMP server and archive your RTMP live stream as-is without transcoding. | |
# Prerequisites: ffmpeg. | |
# Configure your RTMP source to stream to rtmp://your-ip-address:5555/. | |
ffmpeg -listen 1 -i rtmp://0.0.0.0:5555 -c copy -c:v copy -c:a copy your-video.m4v |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Inspired from https://github.com/adriancooney/console.image | |
async function getBlobURL(base64) { | |
const res = await fetch(`data:image/png;base64,${base64}`); | |
const blob = await res.blob(); | |
return URL.createObjectURL(blob); | |
} | |
async function getImageSize(url) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function parseURLSearchParams(search) { | |
return search | |
.replace(/^\?/, '') | |
.split('&') | |
.reduce((params, keyValue) => { | |
const [key, value] = keyValue.split('='); | |
const decodedKey = decodeURIComponent(key); | |
if (key && key !== '__proto__' && key !== 'constructor' && key !== 'prototype') { | |
params[decodedKey] = decodeURIComponent(value); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function interceptObservable(observable, middleware) { | |
return new Observable(observer => { | |
const initializedMiddleware = middleware(observer); | |
const subscription = observable.subscribe({ | |
close() { | |
observer.close(); | |
}, | |
error(err) { | |
observer.error(err); | |
}, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function setIntervalAsync(fn, interval) { | |
let stopped; | |
let timeout; | |
const schedule = () => { | |
timeout = setTimeout(async () => { | |
await fn(); | |
stopped || schedule(); | |
}, interval); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useCallback } from 'react'; | |
import useReducerWithSaga from './useReducerWithSaga'; | |
import saga from '../data/saga'; | |
const DEFAULT_STATE = { | |
localStream: null, | |
remoteStreams: [] | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useRef } from 'react'; | |
export default function useDebugDeps(depsMap, name) { | |
const lastDepsMapRef = useRef({}); | |
const { current: lastDepsMap } = lastDepsMapRef; | |
const keys = new Set([...Object.keys(depsMap), ...Object.keys(lastDepsMap)]); | |
const keysChanged = Array.from(keys).filter(key => !Object.is(depsMap[key], lastDepsMap[key])); | |
if (keysChanged.length) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default function useDetectDepsChange(deps) { | |
const prevDeps = useRef([]); | |
deps.forEach((value, index) => { | |
if (prevDeps.current[index] !== value) { | |
console.log('Dep changed', { index, dep, prevDep: prevDeps.current[index] }); | |
} | |
}); | |
prevDeps.current = [...deps]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const TOKEN_EXPIRE_AFTER = 300000; | |
// This function will create a memoized fetchCredentials function and reduce the call to the function. | |
// The memoized result is time-sensitive and will be invalidated after 5 minutes (specified in TOKEN_EXPIRE_AFTER). | |
const createMemoizedFetchCredentials = () => { | |
let lastFetch = 0; | |
let lastPromise; | |
return () => { | |
const now = Date.now(); |
NewerOlder