videojs / mux.js

Lightweight utilities for inspecting and manipulating video container formats.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

would like help to create a dummy video

jimmywarting opened this issue · comments

I want to create a dummy 1x1 pixel video that plays nothing for a set durration, I thought MediaSource could be of any help, cuz you can set the duration property and be able to feed the media player with buffers and also be able to seek with it (video.currentTime = x).

lets say i set some variable to be 01:20:15, then I want to generate a <video> tag that plays nothing for 1h 20m and 15s

The lack of skill I'm missing is how could i get this source buffers that i could feed into the MediaSource.
I figure you might have some ideas, cuz i don't know exactly video's are built/constructed


a other thought i had was to generate a Blob that only have one frame that's loops over and over again, with the smallest possible file size kind of like saying "this segment is 1hour long but the frames never changes so there should be no reason for the file to be larger than a few kb and doubling the duration would kind of yield the same filesize - the only thing you have actually changed is some duration or time length property in a segment" if something like that would be possible. then i could just generate a complete video and simply just use DataView to modify the time.

then i don't even need MediaSource or mux.js, i could just use URL.createObjectURL(blob) and play that instead


Another question i have is if it's possible to use a same fragment (buffer) over and over again with MediaSource. isn't it like some fragment indexing or currentTime that each "Box" have that makes it impossible append a particular buffer at a particular time?


another dummy video generator i found was this js source code but it didn't work out for me 😞
I would kind of like to what that guy did but possible without the MediaRecorder and the canvas element if i could

I have tried AudioContext also for a bit, but it looks to be too complicated and i can't figure out to create a AudioBuffer that could loop for a set duration and have it play in a <video> tag, I manage to create a looping audio but i wasn't able to seek/jump and the duration was === infinity

fyi, i tried, succeeded and then failed... i had generated a pretty static video with:

ffmpeg -f lavfi -i color=c=black@0.2:size=2x2:duration=1:rate=0.00013888 "2x2 2h.webm"
ffmpeg -i "2x2 2h.webm" "2x2 2h.mp4"

The idea of it all was to have a 1 sec - 1 frame - 2x2 static colored video that could be adjusted how long it would run, by only changing some duration and framerate
This meant that it would have the same filesize... so just changing any hex values would yield a different duration

And at the end i came up with this over engineered (partly) failed attempt

const makeDummyVideo = (() => {
  const gzipDummyVid = 'data:a/a;base64,H4sIAAAAAAAAE41UQYskNRRO9egii+AiCnNYIep6m66pqu6Z7Wk2MDIu9kFZLy4iQpFKUl1FVyqZJN3TvacVPMwvWP+AKAt69iQMogcR7w4KIoIoC+7Rm+1L9cxOzSwrhkrel7zvvZf3XlUhhHDuFrq0SiLUQV7CTOiMxVL3Y4TQM7kRAnQ/SE4dyC8uPb1c3v/55p9f/X48+vLexo/4+NW/Hs6T7T7uYqaMwPHWFjbJTnwdR3TQ5zsDUIxCIGy+/c7NN7t9/PrtPWBywUCxp/SiErnDSRT1ukkUe3bhnB5ubh4cHISzkgtV0TpUZrzpo4SFkxVwlHalqu0QM5pRRmJsRE56mIusUmxC4mE0jDCtabWwgkTz3jCax3EPS0EKMcd2mgG6jrVdgCmsqeEkDiMwggXLci546j3GYJEaWo8FibcxK4ySNAXTGDsjqqq0gAbzAWcOANuXJIIrUH5H1YIk8UYc45xal2o7KbVnrBzs61TluRWOdBPsCgMW3lGl1IQWsEnPzmxVMnF2EOHaNDFYKanz9yhrJ0xFgQTnWTU1dJEyJTV1sGdQImdoWYMLIBrqObmhUlgoVpbqBeCSkwQw5VT7LLI0K6mPxEsjmrwORDkuXAZIaVGnY6VBuzrUYDoRC/BNkq3oBKayrP3VmagFmzrSj3AT3FfUCFuAtWHpo2y93jDCTI5lBmX1WcGGJL0wwvs+FxKF2wC199tIOifbOwCsE5r0camhR/A+QAvBF92H9vtmorvwAl8Rhx+hF5f//P3dw6NPH/z0y4cIrXWkUjPQVXJWcHRurP2Bnr91FwXIP2cjOM+6uN9F/zk68GxAASaAP3CTJubaY9583Ivj/8TtnEyErgnuLMirorLukcWp38Y2+ETykgLAkl/MfRcFGwi9+02z6Ra8Mqca/xm2mbf9ZzmiNa+E5wS3oDM5gBdmsnHavuY1vtJd5dD+VhrPTk2FVzh4zrqsAvyZdZa3OB/7P9ETSuGT7qARyNETGRfH+nIJawxe9wKOLi9/RetjkJ8fp4eHR2+g4OunfGN2b4zuvRegS8WD375/5QgMrmhq9UkAP9eta+p8GjTwdfMpwvVZ+/y8jb3Tugqcdb71JbOOqZZNBDObcud79L4UjfTj5XY/oIeGal21c+uWq6a/dt8p7/Al+GHT06q8RWf51iBMdsI4iv4F63hgsfcFAAA='
  // const dummyVid = 'data:a/a;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAs1tZGF0AAACrQYF//+p3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE1NSByMjkxNyAwYTg0ZDk4IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxOCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTEgbG9va2FoZWFkX3RocmVhZHM9MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50PTI1MCBrZXlpbnRfbWluPTEgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIzLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IGlwX3JhdGlvPTEuNDAgYXE9MToxLjAwAIAAAAAQZYiEABX//vfJ78Cm69vfgQAAAwJtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAST4AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACLHRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAEAAAAAAAST4AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAgAAAAIAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAEk+AAAAAAAAEAAAAAAaRtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAEAAAEsAAFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAFPbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABD3N0YmwAAACnc3RzZAAAAAAAAAABAAAAl2F2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAgACAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwFkAAr/4QAYZ2QACqzZX4iIwEQAAcIEAAADAEA8SJZYAQAGaOvjyyLAAAAAEHBhc3AAAAABAAAAAQAAABhzdHRzAAAAAAAAAAEAAAABAEsAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAYc3RzegAAAAAAAAAAAAAAAQAAAsUAAAAUc3RjbwAAAAAAAAABAAAAMAAAAGJ1ZHRhAAAAWm1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALWlsc3QAAAAlqXRvbwAAAB1kYXRhAAAAAQAAAABMYXZmNTguMjkuMTAw'
  
  // 1. convert b64 to a readable stream
  // 2. pipeThrough a gzip-decompression stream
  // 3. read stream as a arraybuffer and convert to DataView
  const p = fetch(gzipDummyVid).then(res =>
    new Response(
      res.body.pipeThrough(new DecompressionStream('gzip'))
    ).arrayBuffer().then(buffer => new DataView(buffer, 757))
  )

  // alternative way without gzip
  // const p = fetch(dummyVid)
  //   .then(res => res.arrayBuffer())
  //   .then(buffer => new DataView(buffer, 757))

  return sec => p.then(moov => {
    const wantedDuration = sec
    const timedDuration = 16384 / (1 / wantedDuration)
    const wantedMs = wantedDuration * 1000
    moov.setUint32(32, wantedMs)
    moov.setUint32(240, wantedMs)
    moov.setUint32(152, wantedMs)
    moov.setUint32(284, timedDuration)
    moov.setUint32(596, timedDuration)
    return new Blob([moov.buffer], { type: 'video/mp4' })
  })
})()

makeDummyVideo(45).then(blob => {
  const video = document.createElement('video')
  video.controls = true
  video.width = video.height = 300
  video.src = URL.createObjectURL(blob)
  document.body.append(video)
})

And look and behold! It works in chrome: https://jsfiddle.net/8a4dr6bv/
but i should have realized earlier that the generated video won't play in other browser other than chrome and vlc.
Also realized after that i wanted to have a silent audio track as well... and that made it more complicated cuz i could not figure out how to have a audio track that was the same length as the video :/

I have pretty much given up at this point after wasting so many hours trying a bunch of things 😞
Maybe i will try some more by using the MediaSource extension - my hope is to create a live video+audio using one segment that can be reused and hopfully set the mediaSource.duration = x; to whatever value i want and control myself if i want to have a audio, video or both