I'm building a web app that uploads a local .mp4 to an S3 bucket. It's intended for low bandwidth environments. Is it possible to upload every 5th frame of an .mp4 in JavaScript on the frontend and upload this reduced .mp4?
I don't know if it's possible (I didn't find anything online) but it's certainly not easy.
It would be easier to maybe have an endpoint in a server that receives a video and returns a minified version. Like this:
Client --can you minify this video?---> Server
Client <--minified video---- Server
Client ---upload minified video---> S3 bucket
No, it’s not possible. Frames are not independent. Uploading a frame, without uploading the frames it references will crate a corrupt video.
You could make use of FFMPEG in your browser in fact. From ffmpeg.wasm:
ffmpeg.wasm is a pure Webassembly / Javascript port of FFmpeg. It
enables video & audio record, convert and stream right inside
browsers.
Check out the different parameters in regards to your nth frame rate from the documentation on FFMPEG.org.
PS: It might be better solutions to shrink the upload size, ie. compress harder, resize the video dimensions, or combinations of all these, including lowering the frame rate.
Related
I wanna enable users of my web app to upload videos with a maximum lenght of 10s and cropped/scaled to a certain resolution. There for users should be able to trim there selected video to 10s before uploading it with a simple editor.
Is there any library or examples enabling client side video editting to cut video length as well as croping before uploading it to a server? I found some canvas approaches for filters, single video frames and export to webM videos but nothing bringing it all together. So anyone done that before?
Apreciate any ideas :)
Tipicaly video processing is a server thing because it's easier to find and run complex (often compiled) libraries (like ffmpeg) there than in browser and it may cause less performance problems for end user. Anyway I think there are two options:
1. Process video on server - send file and configuration
The first approach assume that you prepare client side "editor" based on canvas which simulate video editing. After setup of all filters, crops etc. the client might send original video file and video processing configuration which would be used on a server to do the same thing
Depends on which language you prefer on backend side implementation might be different so I don't give you ready snippet of code.
Of course you can switch order of tasks and upload original file at first place then smiulate video processing on client side and after all send mentioned configuration to backend and process video.
2. Process video within WebAssembly
If you really need to keep everything on client side you can try with WebAssembly ports of libraries like https://github.com/ffmpegwasm/ffmpeg.wasm and send already processed video file to server.
Client is sending continuous jpg to my server.
The issue is: how to make one mp4 file from all these jpg files?
I can save them all and use ffmpeg with “filename%3d.jpg”, when client finish sending files.
But is there any way to make it real-time?
Yes, there is a way. You can turn it into an mjpeg stream and mux it into an mp4 using any one of the many open source libraries that can do this. Or you can choose to reencode to a more temporal efficient codec such as h.264 to save final file size and bandwidth.
But either way, and MP4 is not usable until the last frame is written, so I'm not sure what the actually gain is from this exercise exercise.
So here's the issue that I'm currently having. I need an audio player for iOS that will play mp3. Now at first glance this may seem like a trivial issue, just create an audio tag and give it the URL to the mp3 file. While this technically works, it's basically unusable since iOS needs to download the entire file before starting to play it. This results in a really long wait time when trying to play large mp3 files (could get close to a minute).
So the first thing I tried was to manually mimic the chunking that chrome does for playing mp3 files. I first sent a HEAD request to get the byte length of the audio file. Used that length / duration in seconds to get the average bytes per second and use that data to request chunks based on where the user seeks to. That didn't work since sometimes mp3 files contain metadata that throw off the calculation (like a cover image). Additionally, sometimes mp3 files use VBR (Variable Bit Rate) and then I'm well and truly screwed.
So this lead me to thinking, Safari couldn't possibly require the end user to download an entire mp4 file before playing it. So I took an mp3 file, converted it to mp4 on an online converter and tested my theory out. Voila, it worked. Safari was streaming the mp4 file in chunks and the wait time went to close to 0. Alright, so now all I need to do is convert mp3 files to mp4 files. The problem now is, I have requirement not to use my server for converting these files. I want to offload this expensive operation to the client. After looking around for a bit I found a few wasm libraries to do this, great! Nope. These wasm libraries are huge (24 MB) and would add an unacceptable amount to my already large bundles files. So this brings me to my question. Is there any way to "trick" safari into thinking that my mp3 file is mp4. What I've tried already:
On input change event -> get the file -> clone it into a new Blob with a mimeType of video/mp4 and then upload that file to the server. Chrome plays this file no problem (probably because it detects it's an mp3 file), on Safari however it's unable to play the file.
So my question is, is there any way to package the mp3 file in an mp4 container (Client Side !important) to "force" Safari into chunking the file.
Is there any way to "trick" safari into thinking that my mp3 file is
mp4
mp4 files are not seekable because the client "thinks" they are mp4. They have an index in the file that is required for the seeking to work. That index does not magically exist because the mime type was changed.
is there any way to package the mp3 file in an mp4 container (Client Side...
Yes, totally. But you must write the code and it is very complicated. You can read ISO 14496-12 document to understand how mp4 files are structured. and ISO 11172-3 and ISO 13818-3 to parse the Mp3 into frames that can be written to the MP4
I did this very thing last month, i only needed it for a 128kbps CBR mp3 live stream so i hard coded something to support that specific format, it can be modified to specifically support different bit rates though, but probably not VBR :/. Posting it here in case its of use to anyone dealing with firefox not playing an mp3 using mediasource extensions: https://gist.github.com/fanfare/0fa525af28b275fd6623942d7e9d70dd
i'm wondering, since HTML and with javascript are mesmerizing together, if there is a solution in HTML5 to generate a video-file from many images?
For example, you're able to load a video into a canvas and make it appear as greyscaled video, by manipulating the canvas. However, I would like to know,
if there is somewhat a method to generate a video-file out of that greyscaled version. Would make sense, if you want to send the video via whatsapp etc.
Thank you
Here we go:
Article: http://techslides.com/convert-images-to-video-with-javascript
Demo: http://techslides.com/demos/image-video/create.html (select multiple images at once)
Code: [just view the source]
You can download .webm video file
#K3N answer mentions building an encoder. Luckily there is one - https://github.com/antimatter15/whammy - snippet from the article:
You need a video encoder and today I just happened to stumble on Whammy, a real time JavaScript WebM Encoder.
There are currently no built-in API to do video encoding in HTML5. There are work in progress though, to allow basic video and audio recording - but it's not available at this time (audio recording is available in FireFox - it is also limited to streams).
If you are OK with gif animation you can encode the frames as a gif using one of the encoders out there (see below).
For video - there has been attempts, more or less successful, (the project I had in mind does not seem to be available anymore) but there has been issues from one browser to another.
There is the option of building an encoder yourself low-level style, following video encoding and file format specifications. It's doable but it's not a small project.
In any case, encoding video is a pretty performance hungry task even for native compiled applications. Running such a task in the browser will be a even more slow process and probably not practical for many users (and mobile devices will suck on those batteries).
The better approach IMO (at the moment at least, until the aforementioned API becomes available), is to send images to server and have a server in the back handling encoding jobs, then send the result to client. This way you can use multi-threading, offload the client, use native compiled encoders such as ffmpeg, and the resulting video can be streamed back.
Some resources
MediaStream Recording API
Gif encoder 1
Gif encoder 2 (NodeJS)
HTML5 Video recording information and status
Realtime video encoder (NodeJS/ffmpeg)
libvpx (requires emscripten/asm.js)
Hi I have built it using the code provided by tech-slides.
Also I made a template application where you can take list of images and turn them into video format. You have to edit the code according to your own needs. It is only supported in chrome and YouTube though. So basically in whammy.js you turn the images into canvas in a JavaScript file then turn the canvas into video using whammy.js function. You need to set event listener and load the videos into video tag. Whammy.js only produce webp file. To turn it into mp4:
Load it in YouTube then download it using YouTube as mp4. Hope it helps.
Just a follow on from #michal's answer, whammy is no longer maintained, however there's a modern fork of whammy encoder at ts-whammy.
See this answer to get a data URL for an image
import tsWhammy from "ts-whammy/src/libs";
// images can from: canvas.toDataURL(type, encoderOptions)
const images = [
"data:image/webp;base64,UklGRkZg....",
"data:image/webp;base64,UklGRkZg....",
];
// Make a 5 second video
const blob = tsWhammy.fromImageArrayWithOptions(images, { duration: 5 });
console.log(blob.type, blob.size);
Is it possible to live stream video (& audio) without using the RTSP protocol? Today I tried out Adobe's Flash Media Server and the free alternative Red5. Both seemed like a bit of an overkill (plus had issues with Red5 not supporting AAC audio).
Basically I'm looking for a way to upload live video to my server so it can be viewed using jwplayer, and then stored so it can be viewed later. Does MP4 support live streaming? So that I can record it client-side then upload it for viewing?
I've been experimenting with uploading jpg images and using a HTML5 canvas to display them so it appears like a video.
Here's my code: (using only a few images)
http://jsfiddle.net/QM5EV/
There's several things wrong with it. For one, it's not efficient because it requires mass amounts of jpg's to be uploaded. And most importantly there's no audio.
What would be best to do? Is RTSP the only sensible choice? Thanks. :)
Live via HTTP servers is, for the most part, not an option. But there is "Apple Live Streaming" aka MPEG-TS, although that limits your clients to iOS devices. It uses a plain ol'web server. (This seems to be changing, increasingly desktop browsers are supporting MPEG-TS, but will probably take some time before it is common place.)
For online streaming, rtsp is the best solution. Other protocols such as RTMP ( http://en.wikipedia.org/wiki/Real_Time_Messaging_Protocol) but transmit to any multimedia content using RTSP.
Another thing is that you can make a specific streaming server accepts HTTP redirect requests. Thus, instead of URL's as rtsp://mydomain.com:554/myfile.mp4 can have URL's like http://mydomain.com/myfile.mp4
Regards!