Giter Site home page Giter Site logo

quasarstream / python-ffmpeg-video-streaming Goto Github PK

View Code? Open in Web Editor NEW
828.0 22.0 142.0 938 KB

πŸ“Ό Package media content for online streaming(DASH and HLS) using FFmpeg

Home Page: https://www.quasarstream.com/op/python/ffmpeg-streaming?u=py-ff

License: MIT License

Python 100.00%
ffmpeg python python-ffmpeg video video-streaming dynamic-adaptive-streaming-http mpeg-dash hls hls-live-streaming http-live-streaming

python-ffmpeg-video-streaming's Introduction

πŸ“Ό Python FFmpeg Video Streaming

Downloads

This package utilizes FFmpeg to bundle media content for online streaming, including DASH and HLS. Additionally, it provides the capability to implement DRM for HLS packaging. The program offers a range of options to open files from cloud storage and save files to cloud storage as well.

Documentation

Full Documentation is available describing all features and components.

Basic Usage

from ffmpeg_streaming import Formats, Bitrate, Representation, Size

_360p = Representation(Size(640, 360), Bitrate(276 * 1024, 128 * 1024))
_480p = Representation(Size(854, 480), Bitrate(750 * 1024, 192 * 1024))
_720p = Representation(Size(1280, 720), Bitrate(2048 * 1024, 320 * 1024))

hls = video.hls(Formats.h264())
hls.representations(_360p, _480p, _720p)
hls.output('/var/media/hls.m3u8')

Get from Basic, Pro, and Enterprise packages for Video Streaming

Our service enables you to save a significant amount of time and resources, allowing you to concentrate on the essential features of your OTT platform without worrying about time-consuming boilerplate code. Our cost-effective solution starts at $78, giving you the flexibility to focus on your core competencies and accelerate your development process. By utilizing our service, you can improve your productivity, reduce your development time, and deliver top-quality results. Don't let the burden of writing boilerplate code slow you down; let us help you streamline your development process and take your OTT platform to the next level.

Project information

  • BACKEND: Python - Django v5
  • FRONTEND: Javascript ES6 - React v18
  • CONTAINER: Docker

Plans

Features / Plans Basic Pro Enterprise
OAuth 2.0 (Login, Register) βœ… βœ… βœ…
Access-control list (ACL) βœ… βœ… βœ…
Video On-Demand βœ… βœ… βœ…
HLS βœ… βœ… βœ…
DASH βœ… βœ… βœ…
HLS Encryption(Single key and key rotation) βœ… βœ… βœ…
Video Quality Settings (Choose from 144p to 4k and auto mode) βœ… βœ… βœ…
Real-Time Progress Monitoring (progress bar to show the live upload and transcoding progress) βœ… βœ… βœ…
Dark and light theme βœ… βœ… βœ…
Live Streaming (From Browser Webcam, IP Cameras, Live Streaming Software) ⛔️ βœ… βœ…
Custom player skin ⛔️ βœ… βœ…
Monetization: Subscriptons/pay-per-view/ads ⛔️ βœ… βœ…
Advanced Analytics: Views/Watched hours/Visited countries and more ⛔️ βœ… βœ…
Robust DRM Systems: Widevine, FairPlay Streaming and PlayReady ⛔️ βœ… βœ…
Social Media Integration(Like, Comment, Share videos) ⛔️ ⛔️ βœ…
Cloud CDN (Content Delivery Network to Clouds Like Amazon S3, Google Cloud Storage, Microsoft Azure and more) ⛔️ ⛔️ βœ…
Email Service ⛔️ ⛔️ βœ…
Support 3 Months 6 Months Customizable
Price $78 Custom Pricing Available
Get GET THE BASIC PACKAGES CONTACT US
We have demos available. Please CONTACT US to request one.
If you have any questions or doubts, please don't hesitate to contact Amin Yazdanpanah (admin) using this link.

Screenshots

Contributors

Your contribution is crucial to our success, regardless of its size. We appreciate your support and encourage you to read our CONTRIBUTING guide for detailed instructions on how to get involved. Together, we can make a significant impact.

Made with contrib.rocks.

License

The MIT License (MIT). See License File for more information.

python-ffmpeg-video-streaming's People

Contributors

aminyazdanpanah avatar blurrybat avatar corruptedfile2021 avatar dakarxy avatar ddorian avatar diego-treitos avatar facerain avatar forchapeatl avatar percheetah avatar renovate-bot avatar richarddally avatar shalmor avatar syntactical01 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-ffmpeg-video-streaming's Issues

save_to_clouds always raises TypeError

When using example of AWS cloud with some modification I came to discover that save_to_clouds method will always raise TypeError no matter what

Use AWS cloud example code and try it with hls.

def save_to_clouds(clouds, dirname):
    if clouds is not None:
        if type(clouds) != list or type(clouds) != tuple:
            raise TypeError('Clouds must be type of list or tuple')

This condition here should be and and not or because in this case for now it will always raise TypeError no matter what is the type of clouds

Also I have modified the example as the one given in the repo did not work for me. I do not know if it is outdated or I was doing something wrong. Still, here it is:

import ntpath
import os
import tempfile
from os import listdir
from os.path import isfile, join

import boto3
import botocore
from ffmpeg_streaming import Clouds


class AWS(Clouds):
    def __init__(self, access_key, secret_key):
        self.s3 = boto3.resource(
            's3',
            aws_access_key_id=access_key,
            aws_secret_access_key=secret_key,
            region_name='us-east-1')

    def upload_directory(self, directory, **options):
        bucket_name = options.pop('bucket_name', None)
        if bucket_name is None:
            raise ValueError('You should pass a bucket name')
        print("directory is: {}".format(directory))
        files = [f for f in listdir(directory) if isfile(join(directory, f))]
        for file in files:
            print("current file is: {}".format(file))
            full_path_file = os.path.join(directory, file)
            print("full file path is: {}".format(full_path_file))
            self.s3.Object(bucket_name, ntpath.basename(full_path_file)).upload_file(Filename=full_path_file)

    def download(self, filename=None, **options):
        if filename is None:
            tmp = tempfile.NamedTemporaryFile(suffix='_py_ff_vi_st.tmp', delete=False)
            filename = tmp.name

        bucket_name = options.pop('bucket_name', None)
        key = options.pop('key', None)
        if bucket_name is None or key is None:
            raise ValueError('You should pass a bucket name and a key')

        try:
            self.s3.Bucket(bucket_name).download_file(key, filename)
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "404":
                raise RuntimeError("The object does not exist.")
            else:
                raise RuntimeError("Could not connect to the server")

        return filename


def aws_cloud(bucket_name, key, access_key, secret_key, region_name):
    cloud = AWS(aws_access_key_id=access_key,
                aws_secret_access_key=secret_key, region_name=region_name)
    download_options = {
        'bucket_name': bucket_name,
        'key': key,
    }
    upload_options = {
        'bucket_name': bucket_name,
    }

    from_aws_cloud = (cloud, download_options, None)
    to_aws_cloud = (cloud, upload_options)

    return from_aws_cloud, to_aws_cloud

RuntimeError: asyncio.run() cannot be called from a running event loop

runfile('C:/Users/schalava.PARTNERS/Downloads/Projects/Python/DEMOlive/notworking_because_of_ffmpegstreaming_version_dash015p.py', wdir='C:/Users/schalava.PARTNERS/Downloads/Projects/Python/DEMOlive')
Traceback (most recent call last):

File "", line 1, in
runfile('C:/Users/schalava.PARTNERS/Downloads/Projects/Python/DEMOlive/notworking_because_of_ffmpegstreaming_version_dash015p.py', wdir='C:/Users/schalava.PARTNERS/Downloads/Projects/Python/DEMOlive')

File "C:\Users\schalava.PARTNERS\AppData\Local\Continuum\anaconda3\envs\dashpy\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 827, in runfile
execfile(filename, namespace)

File "C:\Users\schalava.PARTNERS\AppData\Local\Continuum\anaconda3\envs\dashpy\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)

File "C:/Users/schalava.PARTNERS/Downloads/Projects/Python/DEMOlive/notworking_because_of_ffmpegstreaming_version_dash015p.py", line 33, in
dash.output('/test212.mpd')

File "C:\Users\schalava.PARTNERS\AppData\Local\Continuum\anaconda3\envs\dashpy\lib\site-packages\ffmpeg_streaming_media.py", line 85, in output
asyncio.run(self._run(ffmpeg_bin, monitor, **options))

File "C:\Users\schalava.PARTNERS\AppData\Local\Continuum\anaconda3\envs\dashpy\lib\asyncio\runners.py", line 34, in run
"asyncio.run() cannot be called from a running event loop")

RuntimeError: asyncio.run() cannot be called from a running event loop

Fail atexit._run_exitfuncs in convertions

Describe the bug
I am using the custom service configuration with minIO, at the end of the conversion I see the error of

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
File "/usr/lib/python3.8/shutil.py", line 788, in move
os.rename(src, real_dst)
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/ffmpeg_streaming_tslt6ddb' -> ''

my code

from SARyS.Apps.Streaming.convert2 import CustomCloud

from ffmpeg_streaming import Formats, Bitrate, Representation, Size, CloudManager
import ffmpeg_streaming

custom = CustomCloud()

video = ffmpeg_streaming.input(
custom,
bucket_name="django-backend-dev-private",
key="23037532_179905455894717_507699614384652288_n.mp4",
)

hls = video.hls(Formats.h264())

_144p = Representation(Size(256, 144), Bitrate(95 * 1024, 64 * 1024))
_240p = Representation(Size(426, 240), Bitrate(150 * 1024, 94 * 1024))
_360p = Representation(Size(640, 360), Bitrate(276 * 1024, 128 * 1024))
_480p = Representation(Size(854, 480), Bitrate(750 * 1024, 192 * 1024))
_720p = Representation(Size(1280, 720), Bitrate(2048 * 1024, 320 * 1024))
_1080p = Representation(Size(1920, 1080), Bitrate(4096 * 1024, 320 * 1024))
_2k = Representation(Size(2560, 1440), Bitrate(6144 * 1024, 320 * 1024))
_4k = Representation(Size(3840, 2160), Bitrate(17408 * 1024, 320 * 1024))

hls.representations(_360p, _720p)

save_to_custom = CloudManager().add(
custom,
bucket_name="django-backend-dev-private",
)

hls.output(
'playlist.m3u8',
clouds=save_to_custom,
)

CustomCloud
from django.core.files.uploadedfile import InMemoryUploadedFile
from ffmpeg_streaming import Clouds
import tempfile
from django_minio_backend import MinioBackend
from os.path import isfile, join, basename
import logging
import sys
import datetime
from os import listdir
import io
import os

class CustomCloud(Clouds):

def upload_directory(self, directory, **options):
    bucket_name = options.pop('bucket_name', None)

    if bucket_name is None:
        raise ValueError('You should pass a bucket name')

    files = [f for f in listdir(directory) if isfile(join(directory, f))]

    storage = MinioBackend(bucket_name=bucket_name)

    content_type = None

    contentType = {
        'm3u8': 'application/x-mpegURL',
        'ts': 'video/MP2T',
        'mp4': 'video/mp4',
    }

    try:
        for file in files:

            try:
                if file.split('.')[1] == 'ts':
                    content_type = contentType['ts']
                elif file.split('.')[1] == 'm3u8':
                    content_type = contentType['m3u8']

                f = io.BytesIO(b'')

                with open(os.path.join(directory, file), 'rb') as zip_file:
                    flength = f.write(zip_file.read())

                metrics = InMemoryUploadedFile(
                    f, None, file, content_type, flength, None
                )

                metrics.seek(0)

                storage._save(file_path_name=join(
                    'streaming', file), content=metrics)
            except Exception as e:
                logging.error('file '+e)
                raise RuntimeError('file', e)

    except Exception as e:
        logging.error('files '+e)
        raise RuntimeError('files', e)

def download(self, filename=None, **options):
    bucket_name = options.pop('bucket_name', None)
    key = options.pop('key', None)

    if bucket_name is None or key is None:
        raise ValueError('You should pass a bucket and key name')

    if filename is None:
        filename = tempfile.NamedTemporaryFile(
            prefix=basename(key), delete=False)
    else:
        filename = open(filename, 'wb')

    try:
        with filename as f:
            storage = MinioBackend(bucket_name=bucket_name)
            file = storage._open(object_name=key)
            for chunk in file.chunks():
                f.write(chunk)

        logging.info("The " + filename.name + " file was downloaded")
    except Exception as e:
        logging.error(e)
        raise RuntimeError(e)

    return filename.name

OS Lubuntu 20.10
ffmpeg version 4.3.1-4ubuntu1 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 10 (Ubuntu 10.2.0-9ubuntu2)

Add option to change hls_time for better scrubbing

Is your feature request related to a problem? Please describe.
Currently when you scrub video in case of HLS, for e.g. in VLC, it gets scrubbed to nearest 10 sec segment. I checked the code and found that hls_time is set to 10 in _command_builder.py

Describe the solution you'd like
Probably the same way minrate/maxrate is set in Reprensentation

Gpu acceleration

Hi!

Thanks a lot for your work! You saved a lot of time for our team. Please let me know if there any chance to use hardware acceleration like CUDA -hwaccel cuvid -c:v h264_cuvid / AMD / Intel Quick Sync

Updating a .m3u8 file

Is your feature request related to a problem? Please describe.
I have a problem of adding new videos to the playlist. I should be able to update (not replace) the .m3u8 file after adding a new video to the input and make it a dynamic streaming whenever i upload a new video.

problem with paths

Describe the bug
Hi, great project you have here.

I am however having a problem with paths. I am using a post request to kick off the hls stream. The problem I am having seems to be with white-space in the file path. i.e /path/to/file.mkv works perfectly however /path/to the/file of choice.mkv raises an ffmpeg runtime error that the path does not exist. (runtimeERROR: path /path/to does not exist)

I believe this is due to the terminal commands for ffmpeg as if I call ffmpeg in the terminal using quotes around white-space parts i.e /path/"to the"/"file of choice".mkv then the command works.

I removed the path checks in the programme to test a quoted path and I still got the error, this time (runtimeERROR: path /path/"to the"/"file of choice".mkv doesnt exist).

I do not understand enough of the python code to dig deeper here. New to coding.

Ive tried the pathlib library to create pureWindows path before sending to the create hls stream but this didn't work either

I am sure there is a simple solution to this I am not seeing, but im just not sure. Id appreciate and help!

Thanks :)

To Reproduce
Steps to reproduce the behavior:

  1. try to use a path with white-space
  2. See error

Expected behavior
paths with white-space to work same as those without

Local machine (please complete the following information):

  • OS: Windows
  • FFMpeg 4.2.1

Additional context
I am sure there is a simple solution I am missing!

Transcodes mp4-file on AWS Cloud to audio only...

Hey aminyazdanpanah,

Amazing code thank you very much for this. When I run the script aws_clouds.py from examples, it seems to transcodes my test key .mp4 file on my bucket in .m3u8 and .ts files using hls. method. It also correctly saves them on my local machine. Strangely all files only store the audio lines.. When I run the final .m3u8 on a browser from S3 it only shows the audio of the key .mp4 file. Might this be a bug?

Thank you in Advance. I know you are strict with questions but you might have an idea...

Best

Broadcasting adaptive streaming Video to all the users

Is your feature request related to a problem? Please describe.
I am working on a personal project and I need a way to broadcast same stream to every user. But it should be an adaptive video. Can you please tell me how that can be achieved.

For example - a video file played to all the users logged in everyone sees the same stream but adaptive.

I know this does not come under this library. But, if you can point me to some right resources to do that

Bug if `clouds` is a tuple (automatically throws a TypeError).

Describe the bug
Within clouds.py the following is a bug:

def save_to_clouds(clouds, dirname):
    if clouds is not None:
        if type(clouds) != list or type(clouds) != tuple:
            raise TypeError('Clouds must be type of list or tuple')
    ....

Note that if clouds is a tuple then the TypeError will be raised because it is not a list. or and and expressions short circuit in python so if the first expression is true it won't go to the next:

print(2 or 3) # Outputs 2
print(0 or 3 or 2) # Outputs 3

Similarly types should not be checked via ==, isinstance if the preferred way to do it in python 🐍, but truly I just need this one spot fixed for my code to work in our docker containers.

Please change the above to:

def save_to_clouds(clouds, dirname):
    if clouds is not None:
        if not isinstance(clouds, (list, tuple)): # Tested in my fork
            raise TypeError('Clouds must be type of list or tuple')
    ....

Spent quite a few hours trying to figure out why my coding was failing even though I gave it a tuple :P.

.mkv fails to transcode

Describe the bug
Can't convert to HLS.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Local machine (please complete the following information):

  • OS: [e.g. Linux]
  • FFMped [e.g. 4.1]

Additional context

RuntimeError: ('ffmpeg failed to execute command: ', 'b\'ffmpeg version 3.4.6-0ubuntu0.18.04.1 Copyright (c) 2000-2019 the FFmpeg developers\\n  built with gcc 7 (Ubuntu 7.3.0-16ubuntu3)\\n  configuration: --prefix=/usr --extra-version=0ubuntu0.18.04.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librubberband --enable-librsvg --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264 --enable-shared\\n  libavutil      55. 78.100 / 55. 78.100\\n  libavcodec     57.107.100 / 57.107.100\\n  libavformat    57. 83.100 / 57. 83.100\\n  libavdevice    57. 10.100 / 57. 10.100\\n  libavfilter     6.107.100 /  6.107.100\\n  libavresample   3.  7.  0 /  3.  7.  0\\n  libswscale      4.  8.100 /  4.  8.100\\n  libswresample   2.  9.100 /  2.  9.100\\n  libpostproc    54.  7.100 / 54.  7.100\\nInput #0, matroska,webm, from \\\'./webapp/vid_app/tmp_files/smallfile.mkv\\\':\\n  Metadata:\\n    ENCODER         : Lavf57.83.100\\n  Duration: 00:00:02.17, start: 0.000000, bitrate: 2682 kb/s\\n    Stream #0:0: Video: h264 (High), yuv420p(progressive), 1280x720, 30 fps, 30 tbr, 1k tbn, 60 tbc (default)\\n    Metadata:\\n      DURATION        : 00:00:02.166000000\\n    Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp (default)\\n    Metadata:\\n      title           : simple_aac\\n      DURATION        : 00:00:02.020000000\\n[NULL @ 0x5639407faec0] [Eval @ 0x7ffd5e7423a0] Undefined constant or missing \\\'(\\\' in \\\'copy\\\'\\n[NULL @ 0x5639407faec0] Unable to parse option value "copy"\\n[NULL @ 0x5639407faec0] Error setting option b to value copy.\\nError setting up codec context options.\\nStream mapping:\\n  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))\\n  Stream #0:1 -> #0:1 (copy)\\n  Stream #0:0 -> #1:0 (h264 (native) -> h264 (libx264))\\n  Stream #0:1 -> #1:1 (copy)\\n  Stream #0:0 -> #2:0 (h264 (native) -> h264 (libx264))\\n  Stream #0:1 -> #2:1 (copy)\\n  Stream #0:0 -> #3:0 (h264 (native) -> h264 (libx264))\\n  Stream #0:1 -> #3:1 (copy)\\n  Stream #0:0 -> #4:0 (h264 (native) -> h264 (libx264))\\n  Stream #0:1 -> #4:1 (copy)\\n    Last message repeated 1 times\\n\'')

smallfile.zip

Representation how to keep aspect ratio

Hi,

is there an option to keep the aspect ratio, when using manual Representations?
Also when using auto_generate_representations original resolution will also be put out.

hls.auto_generate_representations([1080, 720, 480])

When I used this with a 4k file, I also got a 4k stream. Is there an option to only output the specified sizes?

Thanks for the awesome library!

MKV to HLS has no audio

I use the example code in file examples\hls.py to process convert MKV file to HLS. Then I use video.js to play video but fail.
I try to play via VLC has the same issue. (still has video)

Here in the error log in the browser console:

video.js:84 VIDEOJS: ERROR: (CODE:3 MEDIA_ERR_DECODE) audio append of 979216b failed for segment #0 in playlist 0-http://localhost:5000/test3/filename_1080p.m3u8

Origin MKV file:
image

After convert to HLS:
image

H265 Support

Hello,

I wish to have H265 codec using Apple "hevc_videotoolbox". Is there a way to use it or
any plan to provide the functionality in near future?

Ability to use from Video Frames

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

I have a system whereby I use opencv to capture frames and process. I will like to make use of your code, to stream these frames using the HLS protocol to a remote device in real-time.

I think the process is to first figure out to write the video file in 10 seconds chucks to an iO buffer, and get your package to process from there. Will that be possible please?

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Nope not considered anyone

Additional context
Add any other context or screenshots about the feature request here.

Setting custom ffmpeg/ffprobe binary path

I'd like to use python-ffmpeg-video-streaming and set a custom path to the ffmpeg and ffprobe binaries (as opposed to using the value found in the path), as I have multiple custom ffmpeg builds available on my system.

I see the run_command call in _media.py:
run_command: bool = True, ffmpeg_bin: str = 'ffmpeg', monitor: callable = None, **options):

And in _command_builder.py:
def command_builder(ffmpeg_bin: str, media):

How can I override this value without having to modify the code myself & recompile?

Subtitles not displayingβ€”due to not being referenced in manifest?

Thanks for writing this very handy utility!

I have transcoded a video containing a single subtitle track. The renditions do contain separate segmented .vtt files (see screenshot), but subtitles do not show up when the video is viewed in Safari or Chrome using an embedded video.js instance.

I think the problem is that there is no reference to the subtitle files in the manifests (see, for example, https://stackoverflow.com/questions/39631349/hls-live-streaming-subtitle).

I'd be very grateful if you could fix this!

PastedGraphic-5

Edit: I have gotten subtitles to appear by hand-editing the master playlist to reference the subtitle media playlists.

Stream to RTMP Server

I'm trying to send processed video frames to an nginx instance running the rtmp extension. From there the video is streamed to the clients. Is there a way write to an rtmp endpoint?

How to know the original resolution of the video?

I am trying to transcode the video in 144p, 240p, 360p, 480p, 720p resolutions.

Now if the original video is in 144p, then it makes no sense to encode the video in higher resolutions.

So is there any way to know in which resolution the original video is in?

Using list in hls.presentations()

Hi,

When I try to pass a list to HLS presentations function I get an error as below:

File "/var/../env/lib/python3.8/site-packages/ffmpeg_streaming/_hls_helper.py", line 87, in stream_info
    f'BANDWIDTH={rep.bitrate.calc_overall}',
AttributeError: 'list' object has no attribute 'bitrate'

This is my code

presetList = []
rep_1  = Representation(Size(1920,1080), Bitrate(4096 * 1024, 320 * 1024))
                    presetList.append(rep_1)
rep_2 = Representation(Size(1440, 900), Bitrate(2048 * 1024, 320 * 1024))
                    presetList.append(rep_2)

video =  "file.mp4"
video = ffmpeg_streaming.input(video)
completed_destination = "completed.m3u8"
hls = video.hls(Formats.h264())
hls.representations(presetList)
hls.output(completed_destination)

Now, if I run hls.representations(rep_1, rep_2) it works fine but not when I pass a list.

Does anyone know why this error occurs?

run on pythonanywhere.com,ffmpeg failed to execute command,Option not found

my code

    video = ffmpeg_streaming.input(fp)
    hls = video.hls(Formats.h264())
    hls.representations(_360p)
    hls.output('~/video/t1.m3u8')

output

ERROR:root:ffmpeg failed to execute command: b"ffmpeg version 2.8.15-0ubuntu0.16.04.1 Copyright (c) 2000-2018 the FFmpeg developers\n  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 20160609\n  configuration: --prefix=/usr --extra-version=0ubuntu0.16.04.1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv\n  libavutil      54. 31.100 / 54. 31.100\n  libavcodec     56. 60.100 / 56. 60.100\n  libavformat    56. 40.101 / 56. 40.101\n  libavdevice    56.  4.100 / 56.  4.100\n  libavfilter     5. 40.101 /  5. 40.101\n  libavresample   2.  1.  0 /  2.  1.  0\n  libswscale      3.  1.101 /  3.  1.101\n  libswresample   1.  2.101 /  1.  2.101\n  libpostproc    53.  3.100 / 53.  3.100\nUnrecognized option 'hls_fmp4_init_filename'.\nError splitting the argument list: Option not found\n"
Traceback (most recent call last):
  File "../m3u8cmd.py", line 29, in <module>
    main(sys.argv[1])
  File "../m3u8cmd.py", line 23, in main
    hls.output('~/video/t1.m3u8')
  File "/home/ytgl/.local/lib/python3.8/site-packages/ffmpeg_streaming/_media.py", line 93, in output
    self.run(ffmpeg_bin, monitor, **options)
  File "/home/ytgl/.local/lib/python3.8/site-packages/ffmpeg_streaming/_media.py", line 121, in run
    asyncio.run(self.async_run(ffmpeg_bin, monitor, **options))
  File "/usr/lib/python3.8/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.8/asyncio/base_events.py", line 608, in run_until_complete
    return future.result()
  File "/home/ytgl/.local/lib/python3.8/site-packages/ffmpeg_streaming/_media.py", line 112, in async_run
    self._run(ffmpeg_bin, monitor, **options)
  File "/home/ytgl/.local/lib/python3.8/site-packages/ffmpeg_streaming/_media.py", line 106, in _run
    self.pipe, err = process.run()
  File "/home/ytgl/.local/lib/python3.8/site-packages/ffmpeg_streaming/_process.py", line 122, in run
    raise RuntimeError('ffmpeg failed to execute command: ', error)
RuntimeError: ('ffmpeg failed to execute command: ', 'b"ffmpeg version 2.8.15-0ubuntu0.16.04.1 Copyright (c) 2000-2018 the FFmpeg developers\\n  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 20160609\\n  configuration: --prefix=/usr --extra-version=0ubuntu0.16.04.1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv\\n  libavutil      54. 31.100 / 54. 31.100\\n  libavcodec     56. 60.100 / 56. 60.100\\n  libavformat    56. 40.101 / 56. 40.101\\n  libavdevice    56.  4.100 / 56.  4.100\\n  libavfilter     5. 40.101 /  5. 40.101\\n  libavresample   2.  1.  0 /  2.  1.  0\\n  libswscale      3.  1.101 /  3.  1.101\\n  libswresample   1.  2.101 /  1.  2.101\\n  libpostproc    53.  3.100 / 53.  3.100\\nUnrecognized option \'hls_fmp4_init_filename\'.\\nError splitting the argument list: Option not found\\n"')

Why ?
How to solve it ?

CMAF support

Is your feature request related to a problem? Please describe.
CMAF is a newer packaging method that claims to save server space by half and provide low latency.
Here's a description of the same.
It seems FFMPEG also supports this. However, I am absolutely unaware of the switches to be used to make things work.

Describe the solution you'd like
methods to have cmaf support

Save to cloud example unclear

    .package(clouds=to_aws_cloud, progress=transcode_progress)
  File "/home/ubuntu/video-streaming/venv/lib/python3.6/site-packages/ffmpeg_streaming/media.py", line 111, in package
    Export.output, dirname, name, Export._is_tmp_directory = _get_paths(output, self.filename, clouds)
  File "/home/ubuntu/video-streaming/venv/lib/python3.6/site-packages/ffmpeg_streaming/media.py", line 34, in _get_paths
    dirname, name = get_path_info(_input)
  File "/home/ubuntu/video-streaming/venv/lib/python3.6/site-packages/ffmpeg_streaming/utiles.py", line 35, in get_path_info
    os.makedirs(dirname)
  File "/usr/lib/python3.6/os.py", line 220, in makedirs
    mkdir(name, mode)
FileNotFoundError: [Errno 2] No such file or directory: ''

Got the following error when encoding a file in HLS to be saved to AWS cloud, the example didn't mention any parameters for the directory path to be specified.

Subtitle

Is your feature request related to a problem? Please describe.
I'am looking for a way to add subtitle. Not sure is it possible.

Describe the solution you'd like
When we add representations of video we want to be able to add
subtitle too.

mpd streaming issue

After generating the dash playlist I am checking it for the list should play in all different versions. But it's playing only for top resolution. In my case, I have made it for _360p, _480p, _720p,_1080p but when I am accessing it through the master dash file so it's playing for only the 1080p version. A little help will be appreciated

Thanks in advance.

recursion error occurred while using S3 for the input

Describe the bug
a recursion error occurred while using S3 for the input after call hls

To Reproduce
This is a sample code to generate the error:

import ffmpeg_streaming
from ffmpeg_streaming import Formats, S3

s3 = S3(
    endpoint_url="*********************",
    aws_access_key_id="****************",
    aws_secret_access_key="************",
    region_name="us-east-1",
    use_ssl=False
)

video = ffmpeg_streaming.input(s3, bucket_name="foo", key="bar.mp4")
hls = video.hls(Formats.h264())

and this is the Traceback of Recursion Error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/site-packages/ffmpeg_streaming/_input.py", line 139, in method
    media = Media(self)
  File "/usr/local/lib/python3.9/site-packages/ffmpeg_streaming/_media.py", line 246, in __init__
    first_input = dict(copy.deepcopy(_inputs.inputs[0]))
  File "/usr/local/lib/python3.9/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
  File "/usr/local/lib/python3.9/copy.py", line 270, in _reconstruct
    state = deepcopy(state, memo)
  File "/usr/local/lib/python3.9/copy.py", line 146, in deepcopy
    y = copier(x, memo)
  File "/usr/local/lib/python3.9/copy.py", line 230, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/usr/local/lib/python3.9/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
  File "/usr/local/lib/python3.9/copy.py", line 270, in _reconstruct
    state = deepcopy(state, memo)

  ...

  File "/usr/local/lib/python3.9/copy.py", line 146, in deepcopy
    y = copier(x, memo)
  File "/usr/local/lib/python3.9/copy.py", line 230, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/usr/local/lib/python3.9/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
  File "/usr/local/lib/python3.9/copy.py", line 271, in _reconstruct
    if hasattr(y, '__setstate__'):
  File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 606, in __getattr__
    self._service_model.service_id.hyphenize(), item
  File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 629, in _service_model
    return self.meta.service_model
  File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 606, in __getattr__
    self._service_model.service_id.hyphenize(), item
  File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 629, in _service_model
    return self.meta.service_model
  File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 606, in __getattr__
    self._service_model.service_id.hyphenize(), item
  File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 629, in _service_model
    return self.meta.service_model

  ...
  
  File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 606, in __getattr__
    self._service_model.service_id.hyphenize(), item
  File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 629, in _service_model
    return self.meta.service_model
  RecursionError: maximum recursion depth exceeded

Local machine :

  • Python 3.9.2
  • FFMpeg 4.1
  • boto3 1.17.14
  • botocore 1.20.14
  • python-ffmpeg-video-streaming 0.1.14

thanks for your awesome package πŸ‘

Sites that require a login

Hello Amin
Thanks for the article
I want to download a video from a site that, after logging in, has access to its HLS videos
How do I do the login steps in FFmpeg?

Specifying minrate, maxrate and buffsize per representation

Hi,

is it possible to specify minrate, maxrate and buffsize per output?
I looked through the source but couldn't find an option.

Moreover the hls master playlist just uses die bitrate specified in the representation. The real bitrate is different from that and this could make problems.

ultrafast args

Thanks for your awesome package!
How can I add 'ultrafast' arg to FFmpeg?

convert m3u8 to mp4 and use http protocol for downloading converted mp4 file

I want to achieve this use case:

I want to convert m3u8 to mp4 and i would like to do conversion as well as download on same time.

I am running this command

ffmpeg -i ultra.m3u8 -c copy -listen 1 -seekable 1 -f mp4 http://0.0.0.0:8080/test.mp4

when user trigger this url("http://0.0.0.0:8080/test.mp4"), then file start's download, but i am not able to play video.

and i get error when all chunks are read:
[hls @ 0x55da053b4100] Opening 'ultra177.ts' for reading
[tcp @ 0x55da0540f940] Connection to tcp://0.0.0.0:8080 failed: Connection refused
[tcp @ 0x55da05520480] Connection to tcp://0.0.0.0:8080 failed: Connection refused
[tcp @ 0x55da053ca780] Connection to tcp://0.0.0.0:8080 failed: Connection refused
[tcp @ 0x55da05485f80] Connection to tcp://0.0.0.0:8080 failed: Connection refused
[tcp @ 0x55da053ced40] Connection to tcp://0.0.0.0:8080 failed: Connection refused
[tcp @ 0x55da054255c0] Connection to tcp://0.0.0.0:8080 failed: Connection refused
[tcp @ 0x55da0540f940] Connection to tcp://0.0.0.0:8080 failed: Connection refused
[tcp @ 0x55da05435380] Connection to tcp://0.0.0.0:8080 failed: Connection refused
frame=53236 fps=7939 q=-1.0 Lsize= 476447kB time=00:29:36.30 bitrate=2197.3kbits/s speed= 265x
video:446847kB audio:28278kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.278083%

HTTP PUT Method To Upload All The Segments Files To The HTTP Server.

First of All Thank you @aminyazdanpanah For This Library, This Works Fine For Saving Output To Local.

But I am Facing Some Issue In Saving output To Ftp Server and Using The HTTP PUT Method To Upload All The Segments Files To The HTTP Server.

Also I Want to Know In The HLS Method, How To Create And Upload The Master Playlist To The Server Manually.

What is the point of encryption of the transcoded video?

I have encrypted the video, and from Django back-end I am sending the video .m3u8 file path to the front-end.

But I am able to play the video with video.js without sending any authentication credentials to the back-end. So I am not understanding am I doing something wrong, or am I missing something?

custom video representations

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Multilple languages

Would it be possible to add support for multiple audio tracks with multiple languages?

How to pass a main argument like "stream_loop" for hls

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Unable to upload generated mpd files to the cloud directly

from ffmpeg_streaming import GCS, CloudManager
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] ="storage.json"
gcs = GCS()

save_to_gcs = CloudManager().add(gcs, bucket_name="bucket-name")

video = ffmpeg_streaming.input("/var/media/video.mp4")

hls = video.hls(Formats.h264())
hls.auto_generate_representations()

hls.output(clouds=save_to_gcs)

This is not working with all the access using storage.json

Ability to define path of the file to load/upload in cloud storages

Is your feature request related to a problem? Please describe.
There should be an option to pass file path of S3 in ffmpeg_streaming.input() and video.outpu()

Describe the solution you'd like
For eg, if my file is present on S3 at path media/raw/file.mp4 then while calling ffmpeg_streaming.input() there should be a parameter to define the path of the file or existing key parameter should support the value as medta/raw/file.mp4. The same thing should happen when calling .outpu() (file should be saved at a defined location).

TypeError: blob() got an unexpected keyword argument 'folder'

Describe the bug
Getting unexpected keyword argument 'folder'for google cloud storage

To Reproduce
Steps to reproduce the behavior:
from ffmpeg_streaming import GCS, CloudManager, Formats
import logging
import os
import ffmpeg_streaming

logging.basicConfig(filename='streaming.log', level=logging.NOTSET, format='[%(asctime)s] %(levelname)s: %(message)s')

Create a service account key from here: https://console.cloud.google.com/apis/credentials/serviceaccountkey

os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "./creds.json"

if you are on windows, the path should be like: "C:\User\username\Desktop\[YOUR-CREDENTIALS].json"

gcs = GCS()

save_to_gcs = CloudManager().add(gcs, bucket_name="writtn", folder="live_stream/test")

A filename can also be passed to the CloudManager class to change the filename(e.x. CloudManager(filename="hls.m3u8"))

#video = ffmpeg_streaming.input(gcs, bucket_name="writtn", object_name="video.mp4")

you can also open a file from a local path

video = ffmpeg_streaming.input("./test.mp4")

hls = video.hls(Formats.h264())
hls.auto_generate_representations()

hls.output(clouds=save_to_gcs)

# you can also pass a local path to save a copy of files to your server

Expected behavior
it should have taken folder name argument as described.

Screenshots
Traceback (most recent call last):
File "./live_streaming.py", line 24, in
hls.output(clouds=save_to_gcs)
File "/home/nishant/.local/lib/python3.6/site-packages/ffmpeg_streaming/media.py", line 84, in output
clouds.transfer('upload_directory', os.path.dirname(self.output
))
File "/home/nishant/.local/lib/python3.6/site-packages/ffmpeg_streaming/_clouds.py", line 198, in transfer
getattr(cloud[0], method)(path, **cloud[1])
File "/home/nishant/.local/lib/python3.6/site-packages/ffmpeg_streaming/_clouds.py", line 111, in upload_directory
blob = bucket.blob(bucket_name + file, **options)
TypeError: blob() got an unexpected keyword argument 'folder'.

Local machine (please complete the following information):

  • OS: Ubuntu 18.04

Additional context
Add any other context about the problem here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.