Kap icon indicating copy to clipboard operation
Kap copied to clipboard

Streaming to RTMP servers

Open dashcraft opened this issue 5 years ago • 7 comments

Current behaviour

Currently KAP stores the recorded file. It would be nice to be able to store and stream the recorded interface to a rtmp server (twitch, youtube, facebook, etc). Currently the most obvious choice for most streamers on macs, would be OBS. For non tech savvy streamers, however, there is difficulty in getting this stood up creating a barrier of entry for some would-be streamers.

Suggestion

Since KAP already saves as h264 and other valid file formats, could just pass this into a binary like ffmpeg-static + ffmpeg-fluent to then broadcast the recording while downloading simultaneously, or be able to choose.

This is similar in nature to another side project i had started about 6 months ago, using webrtc to ffmpeg to stream the desktop in as few steps as possible.

I thought it would be worth having a discussion about.

dashcraft avatar Feb 20 '19 19:02 dashcraft

It would be nice to be able to store and stream the recorded interface to a rtmp server (twitch, youtube, facebook, etc)

I imagine these streaming services require more than just an RTMP address? Probably a authentication token of some sort? I'm asking, because I'm trying to imagine how it will work with different services. I guess we'll need to implement a plugin API for streaming, so people can make plugins for their favorite service. How do you imagine this will work?

Since KAP already saves as h264 and other valid file formats, could just pass this into a binary like ffmpeg-static + ffmpeg-fluent to then broadcast the recording while downloading simultaneously, or be able to choose.

So ffmpeg is able to stream an incomplete H264 video file?

sindresorhus avatar Feb 20 '19 19:02 sindresorhus

I imagine these streaming services require more than just an RTMP address? Probably a authentication token of some sort?

The services typically require a stream key and a rtmp server address. For example, twitch requires a stream key only, that is particular to your channel.

So ffmpeg is able to stream an incomplete H264 video file?

ffmpeg can do that, but i don't know if that's adviseable. If ffmpeg hits the end of a video file, it automatically concludes streaming, so if the file is still in process and is buffering, ffmpeg can prematurely stop. However, in this instance i would imagine ffmpeg would be more of a secondary path for the data buffer to flow through, ideally. I haven't dug into the aperture library, but if there's a way to give some method a callback for streaming and have it pass a buffer into something, that would be legit.

aperture.createBufferStream(ffmpegProcess) Something like that would take advantage of the aperture performance benefits and ffmpeg wouldn't need to encode anything outside of what's required by the RTMP server.

The same process could be taken advantage of so as to use a socket relay and read the data to a canvas anywhere on the web.

dashcraft avatar Feb 20 '19 19:02 dashcraft

So here is a small code example, if you pass a media buffer into this and fill out the necessary variables, it should stream the media to your twitch.

There's some caveats about file type. This was passing media through the mediaRecorder chrome api as h264, and using toBuffer to turn the media recorder blobs into a buffer.

Some of this is borrowed from another ffmpeg developer, (the events and logs).

const fs = require('fs');
let ffmpeg = require('fluent-ffmpeg');
const ffmpegPath = require('ffmpeg-static').path;
const child_process = require('child_process');
ffmpeg.setFfmpegPath(ffmpegPath);

const twitchStreamKey = 'your key goes here';
const rtmpServerAddr = `rtmp://live-dfw.twitch.tv/app/${twitchStreamKey}`;

function startFfmpeg(){
  let vid;
  if(running == 0){
    vid = child_process.spawn(ffmpegPath, [
      '-i', '-', // <-- This basically allows whatever written to stdin to be the input
      '-framerate', '60',  // <-- Depends on what framerate is being recorded
      '-vcodec', 'libx264', // <-- Video Codec if needed
      '-preset', 'ultrafast', // <-- Presets
      '-pix_fmt', 'yuyv422',  // <-- Helpful for dealing with non standard monitors etc
      '-bufsize', '1000k',  // <-- How big a buffer you want
      '-c:a', 'libmp3lame', // <-- depends on audio input
      '-f', 'flv', // <-- rtmp servers use flv as encoding this should be only encoding on outbound
      rtmpServerAddr 
    ]);
    
    // onClose
    vid.on('close', (code, signal) => {
      console.log('FFmpeg child process closed, code ' + code + ', signal ' + signal);
      video.kill('SIGINT');
    });
    
    // onError
    vid.stdin.on('error', (e) => {
      console.log('Error froms STDIN', e);
    });
    
    // onData
    vid.stderr.on('data', (data) => {
      console.log('Data coming through STDERR:', data.toString());
    });

    // onWrite
    vid.stdin.on('write', (e)=>{
      console.log('something new was written', e);
    })

    running = 1;
    return vid;
  } else{
    return vid;
  }

}

let running = 0
let video;

function ffmpegProcess(e){
    if(running == 0){
      video = startFfmpeg();
    }
    if(running == 1){
      video.stdin.write(e); <-- This is where the video childProcess gets the buffer data
    }
}

module.exports = {
    ffmpegProcess
}

dashcraft avatar Feb 20 '19 19:02 dashcraft

aperture.createBufferStream(ffmpegProcess) Something like that would take advantage of the aperture performance benefits and ffmpeg wouldn't need to encode anything outside of what's required by the RTMP server.

We could definitely do this.

sindresorhus avatar Apr 02 '19 07:04 sindresorhus

I think this is a great idea for another use of Aperture, but I'm not sure if it makes sense to add that functionality to Kap, since we describe it as a screen recorder. Feels like the UI to support that would be pretty unique and disconnected from the rest of the app. Unless we make it super simple, as in you select the area like you always do but when you click record it asks for the server info and starts streaming instead of recording (or maybe both?), without much extra customization

If we rework the plugin system for Kap 4.0, we can also keep something like this in mind as well

karaggeorge avatar Apr 02 '19 13:04 karaggeorge

@uhlhosting https://blog.sindresorhus.com/issue-bumping-e3b9740e2a0

sindresorhus avatar Mar 05 '21 10:03 sindresorhus

@uhlhosting No need for personal attacks. I was not trying to be rude. Issue bumping is just not helpful and will not get this issue resolved faster. Kap is an open-source project we do for fun in our spare time. Streaming has just not been a priority as it's not something we personally need and it's also a large undertaking.

That being said, if anyone wants this, a good pull request is always welcome. That's the beauty of open-source.

sindresorhus avatar Mar 07 '21 08:03 sindresorhus