Skip to content

Commit 0d3de69

Browse files
- add clouds
- bug fixes and other minor improvements
1 parent 8c17a52 commit 0d3de69

10 files changed

Lines changed: 93 additions & 56 deletions

File tree

.appveyor.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ cache:
1111

1212
environment:
1313
global:
14+
COMPOSER_NO_INTERACTION: 1
15+
ANSICON: 121x90 (121x90) # Console colors
16+
1417
ffmpeg_download: https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20190225-f948082-win64-static.zip
1518

1619
matrix:
@@ -36,6 +39,7 @@ install:
3639
# - pip install -r requirements.txt
3740
- pip install requests
3841
- pip install boto3
42+
- pip install azure-storage-blob
3943
- pip install google-cloud-storage
4044
- ps: Start-FileDownload $env:ffmpeg_download
4145

.github/workflows/pythonpackage.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323
pip install requests
2424
pip install boto3
2525
pip install google-cloud-storage
26+
pip install azure-storage-blob
2627
- name: Install ffmpeg
2728
run: |
2829
sudo apt-get update

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ before_install:
55
- pip install requests
66
- pip install boto3
77
- pip install google-cloud-storage
8+
- pip install azure-storage-blob
89
- >
910
[ -f ffmpeg-release/ffmpeg ] || (
1011
curl -O https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz &&

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ verify_ssl = true
77
requests = "2.22.0"
88
boto3 = "1.9.243"
99
google-cloud-storage = "1.20.0"
10+
azure-storage-blob = "2.1.0"
1011

1112
[requires]
1213
python_version = "3.7"

README.md

Lines changed: 73 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
[![PyPI version](https://badge.fury.io/py/python-ffmpeg-video-streaming.svg)](https://badge.fury.io/py/python-ffmpeg-video-streaming)
66
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/LICENSE)
77

8-
This package uses the **[FFmpeg](https://ffmpeg.org)** to package media content for online streaming(DASH and HLS)
8+
## Overview
9+
This package uses the **[FFmpeg](https://ffmpeg.org)** to package media content for online streaming such as DASH and HLS. You can also use **[DRM](https://en.wikipedia.org/wiki/Digital_rights_management)** for HLS packaging. There are several options to open a file from clouds and save files to them as well.
910

1011
**Contents**
1112
- [Requirements](#requirements)
@@ -17,6 +18,7 @@ This package uses the **[FFmpeg](https://ffmpeg.org)** to package media content
1718
- [Encrypted HLS](#encrypted-hls)
1819
- [Progress](#progress)
1920
- [Probe](#probe)
21+
- [Saving Files](#saving-files)
2022
- [Several Open Source Players](#several-open-source-players)
2123
- [Contributing and Reporting Bugs](#contributing-and-reporting-bugs)
2224
- [Credits](#credits)
@@ -43,15 +45,14 @@ There are two ways to open a file:
4345
video = '/var/www/media/videos/test.mp4'
4446
```
4547

46-
#### 2. From a cloud
47-
```python
48-
from ffmpeg_streaming.from_clouds import from_url
48+
#### 2. From Clouds
49+
You can open a file from a cloud by passing a tuple of cloud configuration to the method. There are some options to open a file from **[Amazon Web Services (AWS)](https://aws.amazon.com/)**, **[Google Cloud Storage](https://console.cloud.google.com/storage)**, **[Microsoft Azure Storage](https://azure.microsoft.com/en-us/features/storage-explorer/)**, and a custom cloud.
4950

50-
url = 'https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/examples/_example.mp4?raw=true'
51-
video = from_url(url)
51+
Please **[visit the 'open a file from a cloud' page](https://video.aminyazdanpanah.com/python/start/open-clouds)** to see more examples and usage of these clouds.
52+
```python
53+
video = (google_cloud, download_options, None)
5254
```
53-
**NOTE:** This package uses **[Requests](https://2.python-requests.org/en/master/)** to send and receive files.
54-
55+
5556
### DASH
5657
**[Dynamic Adaptive Streaming over HTTP (DASH)](https://dashif.org/)**, also known as MPEG-DASH, is an adaptive bitrate streaming technique that enables high quality streaming of media content over the Internet delivered from conventional HTTP web servers.
5758

@@ -61,8 +62,6 @@ Create DASH Files:
6162
```python
6263
import ffmpeg_streaming
6364

64-
video = '/var/www/media/videos/test.mp4'
65-
6665
(
6766
ffmpeg_streaming
6867
.dash(video, adaption='"id=0,streams=v id=1,streams=a"')
@@ -75,25 +74,21 @@ You can also create representations manually:
7574
```python
7675
import ffmpeg_streaming
7776
from ffmpeg_streaming import Representation
78-
from ffmpeg_streaming.from_clouds import from_url
79-
80-
url = 'https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/examples/_example.mp4?raw=true'
81-
video = from_url(url)
8277

83-
rep1 = Representation(width=256, height=144, kilo_bitrate=200)
84-
rep2 = Representation(width=426, height=240, kilo_bitrate=500)
85-
rep3 = Representation(width=640, height=360, kilo_bitrate=1000)
78+
rep_144 = Representation(width=256, height=144, kilo_bitrate=200)
79+
rep_240 = Representation(width=426, height=240, kilo_bitrate=500)
80+
rep_360 = Representation(width=640, height=360, kilo_bitrate=1000)
8681

8782
(
8883
ffmpeg_streaming
8984
.dash(video, adaption='"id=0,streams=v id=1,streams=a"')
9085
.format('libx265')
91-
.add_rep(rep1, rep2, rep3)
86+
.add_rep(rep_144, rep_240, rep_360)
9287
.package('/var/www/media/videos/dash/test.mpd')
9388
)
9489

9590
```
96-
See **[DASH examples](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/tree/master/examples)** for more information.
91+
See **[DASH examples](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/tree/master/examples/dash)** for more information.
9792

9893
See also **[DASH options](https://ffmpeg.org/ffmpeg-formats.html#dash-2)** for more information about options.
9994

@@ -105,10 +100,6 @@ HLS resembles MPEG-DASH in that it works by breaking the overall stream into a s
105100
Create HLS files based on original video(auto generate qualities).
106101
```python
107102
import ffmpeg_streaming
108-
from ffmpeg_streaming.from_clouds import from_url
109-
110-
url = 'https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/examples/_example.mp4?raw=true'
111-
video = from_url(url)
112103

113104
(
114105
ffmpeg_streaming
@@ -124,17 +115,15 @@ You can also create representations manually:
124115
import ffmpeg_streaming
125116
from ffmpeg_streaming import Representation
126117

127-
video = '/var/www/media/videos/test.mp4'
128-
129-
rep1 = Representation(width=256, height=144, kilo_bitrate=200)
130-
rep2 = Representation(width=426, height=240, kilo_bitrate=500)
131-
rep3 = Representation(width=640, height=360, kilo_bitrate=1000)
118+
rep_144 = Representation(width=256, height=144, kilo_bitrate=200)
119+
rep_240 = Representation(width=426, height=240, kilo_bitrate=500)
120+
rep_360 = Representation(width=640, height=360, kilo_bitrate=1000)
132121

133122
(
134123
ffmpeg_streaming
135124
.hls(video, hls_time=10, hls_allow_cache=1)
136125
.format('libx264')
137-
.add_rep(rep1, rep2, rep3)
126+
.add_rep(rep_144, rep_240, rep_360)
138127
.package('/var/www/media/videos/hls/test.m3u8')
139128
)
140129
```
@@ -143,15 +132,10 @@ rep3 = Representation(width=640, height=360, kilo_bitrate=1000)
143132
#### Encrypted HLS
144133
The encryption process requires some kind of secret (key) together with an encryption algorithm. HLS uses AES in cipher block chaining (CBC) mode. This means each block is encrypted using the ciphertext of the preceding block. [Learn more](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
145134

146-
You need to pass both `URL to the key` and `path to save a random key` to the `encryption` method:
135+
You need to pass both `URL to the key` and `a path to save a random key on your local machine` to the `encryption` method:
147136

148137
```python
149138
import ffmpeg_streaming
150-
from ffmpeg_streaming.from_clouds import from_url
151-
152-
url = 'https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/examples/_example.mp4?raw=true'
153-
video = from_url(url)
154-
155139
(
156140
ffmpeg_streaming
157141
.hls(video, hls_time=10, hls_allow_cache=1)
@@ -162,7 +146,7 @@ video = from_url(url)
162146
)
163147
```
164148
**NOTE:** It is very important to protect your key on your website using a token or a session/cookie(****It is highly recommended****).
165-
See **[HLS examples](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/tree/master/examples)** for more information.
149+
See **[HLS examples](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/tree/master/examples/hls)** for more information.
166150

167151
See also **[HLS options](https://ffmpeg.org/ffmpeg-formats.html#hls-2)** for more information about options.
168152

@@ -171,23 +155,13 @@ You can get realtime information about transcoding and downloading by passing ca
171155
```python
172156
import sys
173157
import ffmpeg_streaming
174-
from ffmpeg_streaming.from_clouds import from_url
175158

176-
def download_progress(percentage, downloaded, total):
177-
# You can update a field in your database
178-
# You can also create a socket connection and show a progress bar to users
179-
sys.stdout.write("\r Downloading... (%s%%)[%s%s]" % (percentage, '#' * percentage, '-' * (100 - percentage)))
180-
sys.stdout.flush()
181-
182-
183-
def progress(percentage, line, sec):
159+
def progress(percentage, ffmpeg, media):
184160
# You can update a field in your database
185161
# You can also create a socket connection and show a progress bar to users
186162
sys.stdout.write("\r Transcoding... (%s%%)[%s%s]" % (percentage, '#' * percentage, '-' * (100 - percentage)))
187163
sys.stdout.flush()
188164

189-
url = 'https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/examples/_example.mp4?raw=true'
190-
video = from_url(url, progress=download_progress)
191165

192166
(
193167
ffmpeg_streaming
@@ -210,7 +184,57 @@ ffprobe = FFProbe('/var/www/media/test.mp4')
210184
**NOTE:** You can save these metadata to your database.
211185

212186
See the **[example](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/examples/probe.py)** for more information.
187+
### Saving Files
188+
There are several options to save your files.
189+
190+
#### 1. To a Local Path
191+
You can pass a local path to the `package` method. If there was no directory in the path, then the package auto makes the directory.
192+
```python
193+
(
194+
ffmpeg_streaming
195+
.hls(video)
196+
.format('libx264')
197+
.auto_rep()
198+
.package('/var/www/media/videos/hls/test.m3u8', progress)
199+
)
200+
```
201+
It can also be null. The default path to save files is the input path.
202+
```python
203+
(
204+
ffmpeg_streaming
205+
.hls(video)
206+
.format('libx264')
207+
.auto_rep()
208+
.package(progress=progress)
209+
)
210+
```
211+
**NOTE:** If you open a file from cloud and did not pass a path to save a file, you will have to pass a local path to the `package` method.
213212

213+
#### 2. To Clouds
214+
You can save your files to clouds by passing a array of cloud configuration to the `package` method. There are some options to save files to **[Amazon Web Services (AWS)](https://aws.amazon.com/)**, **[Google Cloud Storage](https://console.cloud.google.com/storage)**, **[Microsoft Azure Storage](https://azure.microsoft.com/en-us/features/storage-explorer/)**, and a custom cloud.
215+
216+
Please **[visit the 'save files to clouds' page](https://video.aminyazdanpanah.com/python/start/save-clouds)** to see more examples and usage of these clouds.
217+
```python
218+
(
219+
ffmpeg_streaming
220+
.dash('/var/www/media/video.mkv', adaption='"id=0,streams=v id=1,streams=a"')
221+
.format('libx265')
222+
.auto_rep()
223+
.package(clouds=[to_aws_cloud, to_azure_cloud, to_google_cloud],
224+
progress=progress)
225+
)
226+
```
227+
A path can also be passed to save a copy of files on your local machine.
228+
```python
229+
(
230+
ffmpeg_streaming
231+
.dash('/var/www/media/video.mkv', adaption='"id=0,streams=v id=1,streams=a"')
232+
.format('libx265')
233+
.auto_rep()
234+
.package(output='/var/www/media/stream.mpd', clouds=[to_aws_cloud, to_google_cloud],
235+
progress=progress)
236+
)
237+
```
214238
## Several Open Source Players
215239
You can use these libraries to play your streams.
216240
- **WEB**
@@ -237,10 +261,9 @@ I'd love your help in improving, correcting, adding to the specification.
237261
Please **[file an issue](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/issues)** or **[submit a pull request](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/pulls)**.
238262
- Please see **[Contributing File](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/CONTRIBUTING.md)** for more information.
239263
- If you have any questions or you want to report a bug, please just **[file an issue](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/issues)**
240-
- If you discover a security vulnerability within this package, please see **[SECURITY File](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/SECURITY.md)** for more information to help with that.
241-
242-
**NOTE:** If you have any questions about this package or FFMpeg, please **DO NOT** send an email to me or submit the contact form on my website. Emails related to these issues **will be ignored**.
264+
- If you discover a security vulnerability within this package, please see **[SECURITY File](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/SECURITY.md)** for more information.
243265

266+
**NOTE:** If you have any questions about this package or FFmpeg, please **DO NOT** send an email to me (or submit the contact form on my website). Emails regarding these issues **will be ignored**.
244267

245268
## Credits
246269
- **[Amin Yazdanpanah](https://www.aminyazdanpanah.com/?u=github.com/aminyazdanpanah/python-ffmpeg-video-streaming)**

examples/clouds/cloud.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def main():
4040
upload_options = {
4141
'url': 'https://localhost:8000/api/upload',
4242
'method': 'post',
43+
'field_name': 'YOUR_FIELD_NAME',
4344
'auth': ('username', 'password'),
4445
'headers': {
4546
'User-Agent': 'Mozilla/5.0 (compatible; AminYazdanpanahBot/1.0; +http://aminyazdanpanah.com/bots)',

ffmpeg_streaming/clouds.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
ffmpeg_streaming.clouds
33
~~~~~~~~~~~~
44
5-
Upload and download files to clouds
5+
Upload and download files -> clouds
66
77
88
:copyright: (c) 2019 by Amin Yazdanpanah.
@@ -38,7 +38,11 @@ def download(self, filename=None, **options):
3838
class Cloud(Clouds):
3939

4040
def upload_directory(self, directory, **options):
41-
field_name = options.pop('method', 'get')
41+
field_name = options.pop('field_name', None)
42+
43+
if field_name is None:
44+
raise ValueError('You should specify a field_name')
45+
4246
method = options.pop('method', 'post')
4347
url = options.pop('url', None)
4448
upload_files = []
@@ -116,7 +120,7 @@ def download(self, filename=None, **options):
116120
if e.response['Error']['Code'] == "404":
117121
raise RuntimeError("The object does not exist.")
118122
else:
119-
raise RuntimeError("Could not connect to server")
123+
raise RuntimeError("Could not connect to the server")
120124

121125
return filename
122126

ffmpeg_streaming/utiles.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def convert_to_sec(time):
4343

4444
def deprecated(func):
4545
def deprecated_fun(*args, **kwargs):
46-
warnings.warn('This method is deprecated and will be removed in the next release.'
46+
warnings.warn('The {} method is deprecated and will be removed in a future release'.format(func.__name__)
4747
, DeprecationWarning, stacklevel=2)
4848
return func(*args, **kwargs)
4949
return deprecated_fun

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
requests==2.22.0
22
boto3==1.9.243
3-
google-cloud-storage==1.20.0
3+
google-cloud-storage==1.20.0
4+
azure-storage-blob==2.1.0

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
'requests>=2.22.0,<2.20.0',
55
'boto3>=1.9.243,<1.9.1',
66
'google-cloud-storage>=1.20.0,<1.19.0'
7+
'azure-storage-blob>=2.1.0,<2.0.0'
78
]
89

910
with open("README.md", "r") as fh:
1011
long_description = fh.read()
1112

1213
setuptools.setup(
1314
name="python-ffmpeg-video-streaming",
14-
version="0.0.12",
15+
version="0.0.13",
1516
author="Amin Yazdanpanah",
1617
author_email="[email protected]",
1718
description="Package media content for online streaming(DASH and HLS) using ffmpeg",

0 commit comments

Comments
 (0)