Frameserve to external ffmpeg?
https://lists.ffmpeg.org/pipermail/ffmpeg-user/2015-July/027532.html
First Solution
My first solution involves taking the rendered image, saving it to a single tmp.png, then appending that to an ffmpeg mp4 at the end of every frame.
First we need to bootstrap
ffmpeg -r 24 -f concat -safe 0 -i video-input-list.txt -safe 0  -pix_fmt yuv420p -crf 23 -r 24 -shortest -y video-from-frames.mp4

video-input-list.txt looks something like this:
file 'tmp.png'

next we need to copy the frame's boostrapped video into a temp video with do_ffmpeg_with_tmp.sh :
ffmpeg -i input1.mp4 -filter_complex &quot;concat=n=2:v=1:a=0&quot; -r 24 -f concat -safe 0 -i video-input-list.txt -safe 0  -pix_fmt yuv420p -crf 23 -r 24 -shortest -y video-from-frames.mp4```
This ends up copying the video to a temp as well since the input cannot be the same as the output in ffmpeg. 

Next we need to call all this in Blender : 
```import bpy
def render_image():
    print(&quot;after render&quot;, bpy.data.filepath)
    scene = bpy.context.scene
    scene.render.image_settings.file_format = 'PNG'
    scene.render.filepath = &quot;tmp.png&quot;
    bpy.ops.render.render(write_still = 1)
    os.system(&quot;do_ffmpeg_with_tmp.sh&quot;)
    # increment to next frame
    
while bpy.context.scene.frame_current &lt;= bpy.context.scene.frame_end:
    render_image()
    bpy.context.scene.frame_set(bpy.context.scene.frame_current +1 ) 

This is all to say that doing it with a video and image buffer that ffmpeg concats at the end of every frame is doable, but image sequences are better. if you're worried about space, you could write a script similar to this one that changes the location of the storage after every 1000 frames or so, then compile the files together later through image sequences and video concatenations.
Second Solution - piping output
I looked into getting a pipe out from blender:
The main issue is that blender is noisy and piping out
If you want blender to pipe you need to have it return a png image and flush stdout.
ffmpeg cannot read a piped in image without image2pipe https://superuser.com/questions/426193/multiple-png-images-over-a-single-pipe-to-ffmpeg-no-file-writes-to-disk.
We convert image to png data and send it accross the noisy wire.
import base64
import zlib
import struct
import sys
import os
def render_image():
    print(&quot;after render&quot;, bpy.data.filepath)
    scene = bpy.context.scene
    scene.render.image_settings.file_format = 'PNG'
    scene.render.filepath = &quot;./tmp.png&quot;
    bpy.ops.render.render(write_still = 0)

def png_to_base64(png_bytes):
    return 'data:image/png;base64,' + base64.b64encode(png_bytes).decode()

def img_to_png(blender_image):
    width = blender_image.size[0]
    height = blender_image.size[1]
    buf = bytearray([int(p * 255) for p in blender_image.pixels])

    # reverse the vertical line order and add null bytes at the start
    width_byte_4 = width * 4
    raw_data = b''.join(b'\x00' + buf[span:span + width_byte_4]
                        for span in range((height - 1) * width_byte_4, -1, - width_byte_4))

    def png_pack(png_tag, data):
        chunk_head = png_tag + data
        return (struct.pack(&quot;!I&quot;, len(data)) +
                chunk_head +
                struct.pack(&quot;!I&quot;, 0xFFFFFFFF &amp; zlib.crc32(chunk_head)))

    png_bytes = b''.join([
        b'\x89PNG\r\n\x1a\n',
        png_pack(b'IHDR', struct.pack(&quot;!2I5B&quot;, width, height, 8, 6, 0, 0, 0)),
        png_pack(b'IDAT', zlib.compress(raw_data, 9)),
        png_pack(b'IEND', b'')])

    return png_bytes

render_image()
bpy.data.images['Render Result'].save_render(&quot;/tmp/tmp.png&quot;)
r2 = bpy.data.images.load(&quot;/tmp/tmp.png&quot;)
print(&quot;*#*#*#&quot;)
print(img_to_png(r2))
#file = open('/tmp/stufff.png','wb')
#file.write(img_to_png(r2))
#file.close()
sys.stdout.flush()
print(&quot;*#*#*#&quot;)

To compensate for the noise we use a runner:
import sys
from subprocess import check_output
render_progress = check_output(['blender','--background','--python','pipe_image.py','scripting_ffmpeg.blend'])
msg = render_progress.split('*#*#*#')[1]

print(msg)
sys.stdout.flush()

This is what we use to pipe png files out. However the only remaining problem to be solved is to pass the frame in through the runner and find the amount left in the render, and to put the runner in a while loop to output piped data.
This should provide piped image output to the ffmpeg. Its a very complex process.Maybe even needlessly so. I explored it though.