Skip to content

Commit c8c24dd

Browse files
- Add stream to file
- support other types of input and output
1 parent 671d58d commit c8c24dd

17 files changed

Lines changed: 416 additions & 46 deletions

README.md

Lines changed: 104 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ This package uses the **[FFmpeg](https://ffmpeg.org)** to package media content
1616
- [Requirements](#requirements)
1717
- [Installation](#installation)
1818
- [Quickstart](#quickstart)
19-
- [Opening a File](#opening-a-file)
19+
- [Opening a Resource](#opening-a-resource)
2020
- [DASH](#dash)
2121
- [HLS](#hls)
2222
- [Encrypted HLS](#encrypted-hls)
2323
- [Progress](#progress)
2424
- [Saving Files](#saving-files)
2525
- [Probe](#probe)
26+
- [Live](#live)
27+
- [Conversion](#conversion)
2628
- [Several Open Source Players](#several-open-source-players)
2729
- [Contributing and Reporting Bugs](#contributing-and-reporting-bugs)
2830
- [Credits](#credits)
@@ -41,26 +43,32 @@ pip install python-ffmpeg-video-streaming
4143

4244
## Quickstart
4345

44-
### opening a file
46+
### Opening a Resource
4547
There are two ways to open a file:
46-
#### 1. From a Local Path
48+
49+
#### 1. From a FFmpeg supported resources
50+
You can pass a local path of video(or a supported resource) to the `open` method:
4751
```python
4852
video = '/var/www/media/videos/video.mp4'
4953
```
5054

55+
For opening a file from a supported FFmpeg resource such as `http`, `ftp`, `pipe`, `rtmp` and etc. please see **[FFmpeg Protocols Documentation](https://ffmpeg.org/ffmpeg-protocols.html)**
56+
57+
**For example:**
58+
```python
59+
video = 'https://www.aminyazdanpanah.com/PATH/TO/VIDEO.MP4'
60+
```
61+
5162
#### 2. From Clouds
52-
You can open a file from a cloud by passing a tuple of cloud configuration to the method.
53-
54-
In **[this page](https://video.aminyazdanpanah.com/python/start/clouds?r=open)**, you will find some examples of opening a file from **[Amazon S3](https://aws.amazon.com/s3)**, **[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.
63+
You can open a file from a cloud by passing an array of cloud configuration to the `openFromCloud` method.
5564

65+
In **[this page](https://video.aminyazdanpanah.com/python/start/clouds?r=open)**, you will find some examples of opening a file from **[Amazon S3](https://aws.amazon.com/s3)**, **[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.
5666
```python
5767
video = (google_cloud, download_options, None)
5868
```
5969

60-
6170
### DASH
62-
**[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. [Learn more](https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP)
63-
71+
**[Dynamic Adaptive Streaming over HTTP (DASH)](http://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. [Learn more](https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP)
6472

6573
Create DASH files:
6674
```python
@@ -101,7 +109,7 @@ See **[DASH examples](https://github.com/aminyazdanpanah/python-ffmpeg-video-str
101109

102110
### HLS
103111
**[HTTP Live Streaming (also known as HLS)](https://developer.apple.com/streaming/)** is an HTTP-based adaptive bitrate streaming communications protocol implemented by Apple Inc. as part of its QuickTime, Safari, OS X, and iOS software. Client implementations are also available in Microsoft Edge, Firefox and some versions of Google Chrome. Support is widespread in streaming media servers. [Learn more](https://en.wikipedia.org/wiki/HTTP_Live_Streaming)
104-
112+
105113
Create HLS files:
106114
```python
107115
import ffmpeg_streaming
@@ -166,7 +174,6 @@ See **[HLS examples](https://github.com/aminyazdanpanah/python-ffmpeg-video-stre
166174
You can get realtime information about transcoding by passing a callable method to the `package` method:
167175
```python
168176
import sys
169-
170177
import ffmpeg_streaming
171178

172179

@@ -185,7 +192,7 @@ def progress(percentage, ffmpeg):
185192
.package('/var/www/media/videos/hls/hls-stream.m3u8', progress=progress)
186193
)
187194
```
188-
Output from a terminal:
195+
##### Output From a Terminal:
189196
![transcoding](https://github.com/aminyazdanpanah/aminyazdanpanah.github.io/blob/master/video-streaming/transcoding.gif?raw=true "transcoding" )
190197

191198
### Saving Files
@@ -212,10 +219,10 @@ It can also be null. The default path to save files is the input path.
212219
.package(progress=progress)
213220
)
214221
```
215-
**NOTE:** If you open a file from a cloud and do not pass a path to save the file to your local machine, you will have to pass a local path to the `package` method.
222+
**NOTE:** If you open a file from a cloud and do not pass a path to save the file to your local machine, you will have to pass a local path to the `save` method.
216223

217224
#### 2. To Clouds
218-
You can save your files to clouds by passing an array of clouds configuration to the `package` method.
225+
You can save your files to a cloud by passing an array of cloud configuration to the `package` method.
219226

220227
In **[this page](https://video.aminyazdanpanah.com/python/start/clouds?r=save)**, you will find some examples of saving files to **[Amazon S3](https://aws.amazon.com/s3)**, **[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.
221228

@@ -240,8 +247,10 @@ A path can also be passed to save a copy of files to your local machine.
240247
progress=progress)
241248
)
242249
```
250+
**NOTE:** This option(Save To Clouds) is only for **[VOD](https://en.wikipedia.org/wiki/Video_on_demand)** (it does not support live streaming).
243251

244252
**Schema:** The relation is `one-to-many`.
253+
245254
<p align="center"><img src="https://github.com/aminyazdanpanah/aminyazdanpanah.github.io/blob/master/video-streaming/video-streaming.gif?raw=true" width="100%"></p>
246255

247256
### Probe
@@ -255,17 +264,91 @@ ffprobe = FFProbe('/var/www/media/video.mp4')
255264

256265
See the **[example](https://github.com/aminyazdanpanah/python-ffmpeg-video-streaming/blob/master/examples/probe.py)** for more information.
257266

267+
### Live
268+
You can pass a url(or a supported resource like `ftp`) to live method to upload all the segments files to the HTTP server(or other protocols) using the HTTP PUT method, and update the manifest files every refresh times.
269+
270+
If you want to save stream files to your local machine, please use the `package` method.
271+
272+
```python
273+
# DASH live
274+
import ffmpeg_streaming
275+
276+
(
277+
ffmpeg_streaming
278+
.dash('/var/www/media/video.avi', adaption='"id=0,streams=v id=1,streams=a"')
279+
.format('libx265')
280+
.auto_rep()
281+
.live('http://YOUR-WEBSITE.COM/live-stream/out.mpd', progress=progress)
282+
)
283+
284+
# HLS live
285+
(
286+
ffmpeg_streaming
287+
.hls('/var/www/media/video.mp4', master_playlist_path='/var/www/stream/live-master-manifest.m3u8')
288+
.format('libx264')
289+
.auto_rep()
290+
.live('http://YOUR-WEBSITE.COM/live-stream/out.m3u8', progress=progress)
291+
)
292+
```
293+
**NOTE:** In the HLS streaming method, you should pass the master playlist to your player. So you should upload the master manifest to your server as well as other files.
294+
295+
Please see **[FFmpeg Protocols Documentation](https://ffmpeg.org/ffmpeg-protocols.html)** for more information.
296+
297+
### Conversion
298+
You can convert your stream to a file or to another stream protocols. You should pass a manifest of a stream to the method:
299+
300+
#### 1. HLS To DASH
301+
```python
302+
import ffmpeg_streaming
303+
from ffmpeg_streaming import Representation
304+
305+
r_360p = Representation(width=640, height=360, kilo_bitrate=276)
306+
307+
(
308+
ffmpeg_streaming
309+
.dash('https://www.aminyazdanpanah.com/PATH/TO/HLS-MANIFEST.M3U8')
310+
.format('libx265')
311+
.add_rep(r_360p)
312+
.package('/var/www/media/dash-stream.mpd', progress=progress)
313+
)
314+
```
315+
316+
#### 2. DASH To HLS
317+
```python
318+
import ffmpeg_streaming
319+
320+
(
321+
ffmpeg_streaming
322+
.hls('https://www.aminyazdanpanah.com/PATH/TO/DASH-MANIFEST.MPD')
323+
.format('libx264')
324+
.auto_rep(heights=[360, 240])
325+
.package('/var/www/media/hls-stream.mpd', progress=progress)
326+
)
327+
```
328+
329+
#### 3. Stream(DASH or HLS) To File
330+
```python
331+
import ffmpeg_streaming
332+
333+
(
334+
ffmpeg_streaming
335+
.stream2file('https://www.aminyazdanpanah.com/PATH/TO/MANIFEST.MPD or M3U8')
336+
.format('libx264')
337+
.save('/var/www/media/new-video.mp4', progress=progress)
338+
)
339+
```
340+
258341
## Several Open Source Players
259342
You can use these libraries to play your streams.
260343
- **WEB**
261344
- DASH and HLS:
262-
- **[Shaka Player](https://github.com/google/shaka-player)**
263-
- **[Flowplayer](https://github.com/flowplayer/flowplayer)**
264-
- **[videojs-http-streaming (VHS)](https://github.com/videojs/http-streaming)**
265-
- **[MediaElement.js](https://github.com/mediaelement/mediaelement)**
345+
- **[Video.js 7](https://github.com/videojs/video.js) - [videojs-http-streaming (VHS)](https://github.com/videojs/http-streaming)**
346+
- **[Plyr](https://github.com/sampotts/plyr)**
266347
- **[DPlayer](https://github.com/MoePlayer/DPlayer)**
348+
- **[MediaElement.js](https://github.com/mediaelement/mediaelement)**
267349
- **[Clappr](https://github.com/clappr/clappr)**
268-
- **[Plyr](https://github.com/sampotts/plyr)**
350+
- **[Shaka Player](https://github.com/google/shaka-player)**
351+
- **[Flowplayer](https://github.com/flowplayer/flowplayer)**
269352
- DASH:
270353
- **[dash.js](https://github.com/Dash-Industry-Forum/dash.js)**
271354
- HLS:
@@ -283,6 +366,8 @@ You can use these libraries to play your streams.
283366
- **[FFmpeg(ffplay)](https://github.com/FFmpeg/FFmpeg)**
284367
- **[VLC media player](https://github.com/videolan/vlc)**
285368

369+
As you may know, **[IOS](https://www.apple.com/ios)** does not have native support for DASH. Although there are some libraries such as **[Viblast](https://github.com/Viblast/ios-player-sdk)** and **[MPEGDASH-iOS-Player](https://github.com/MPEGDASHPlayer/MPEGDASH-iOS-Player)** to support this technique, I have never tested them. So if you know any IOS player that supports DASH Stream and also works fine, please add it to the above list.
370+
286371
**NOTE:** You should pass a manifest of stream(e.g. `https://www.aminyazdanpanah.com/PATH_TO_STREAM_DIRECTORY/dash-stream.mpd` or `/PATH_TO_STREAM_DIRECTORY/hls-stream.m3u8` ) to these players.
287372

288373
## Contributing and Reporting Bugs

examples/conversion/dash_to_hls.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
examples.conversion.dash_to_hls
3+
~~~~~~~~~~~~
4+
5+
Convert DASH stream to HLS stream
6+
7+
8+
:copyright: (c) 2020 by Amin Yazdanpanah.
9+
:website: https://www.aminyazdanpanah.com
10+
11+
:license: MIT, see LICENSE for more details.
12+
"""
13+
14+
import argparse
15+
import sys
16+
import logging
17+
18+
import ffmpeg_streaming
19+
20+
21+
logging.basicConfig(filename='streaming.log', level=logging.NOTSET, format='[%(asctime)s] %(levelname)s: %(message)s')
22+
23+
24+
def progress(per, ffmpeg):
25+
sys.stdout.write("\n%s%% - %s" % (per, ffmpeg))
26+
27+
28+
def main():
29+
parser = argparse.ArgumentParser()
30+
parser.add_argument('-i', '--input', required=True,
31+
help='A URL to DASH manifest e.x. http://website.com/dash-manifest.mpd (required).')
32+
parser.add_argument('-o', '--output', default=None, help='The output to write files.')
33+
args = parser.parse_args()
34+
35+
(
36+
ffmpeg_streaming
37+
.hls(args.input)
38+
.format('libx264')
39+
.auto_rep(heights=[360, 240])
40+
.package(args.output, progress=progress)
41+
)
42+
43+
44+
if __name__ == "__main__":
45+
sys.exit(main())

examples/conversion/hls_to_dash.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
examples.conversion.hls_to_dash
3+
~~~~~~~~~~~~
4+
5+
Convert HLS stream to DASH stream
6+
7+
8+
:copyright: (c) 2020 by Amin Yazdanpanah.
9+
:website: https://www.aminyazdanpanah.com
10+
11+
:license: MIT, see LICENSE for more details.
12+
"""
13+
14+
import argparse
15+
import sys
16+
import logging
17+
18+
import ffmpeg_streaming
19+
from ffmpeg_streaming import Representation
20+
21+
logging.basicConfig(filename='streaming.log', level=logging.NOTSET, format='[%(asctime)s] %(levelname)s: %(message)s')
22+
23+
24+
def progress(per, ffmpeg):
25+
sys.stdout.write("\n%s%% - %s" % (per, ffmpeg))
26+
27+
28+
def main():
29+
parser = argparse.ArgumentParser()
30+
parser.add_argument('-i', '--input', required=True,
31+
help='A URL to HLS manifest e.x. http://website.com/hls-manifest.m3u8 (required).')
32+
parser.add_argument('-o', '--output', default=None, help='The output to write files.')
33+
args = parser.parse_args()
34+
35+
r_360p = Representation(width=640, height=360, kilo_bitrate=276)
36+
37+
(
38+
ffmpeg_streaming
39+
.dash(args.input)
40+
.format('libx265')
41+
.add_rep(r_360p)
42+
.package(args.output, progress=progress)
43+
)
44+
45+
46+
if __name__ == "__main__":
47+
sys.exit(main())
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
examples.conversion.stream_to_file
3+
~~~~~~~~~~~~
4+
5+
Convert a stream(DASH or HLS) to File
6+
7+
8+
:copyright: (c) 2020 by Amin Yazdanpanah.
9+
:website: https://www.aminyazdanpanah.com
10+
11+
:license: MIT, see LICENSE for more details.
12+
"""
13+
14+
import argparse
15+
import sys
16+
import logging
17+
18+
import ffmpeg_streaming
19+
20+
logging.basicConfig(filename='streaming.log', level=logging.NOTSET, format='[%(asctime)s] %(levelname)s: %(message)s')
21+
22+
23+
def progress(per, ffmpeg):
24+
sys.stdout.write("\n%s%% - %s" % (per, ffmpeg))
25+
26+
27+
def main():
28+
parser = argparse.ArgumentParser()
29+
parser.add_argument('-i', '--input', required=True,
30+
help='A URL to a stream manifest (HLS or DASH) (required).')
31+
parser.add_argument('-o', '--output', default=None,
32+
help='The output to write a file. e.x. /var/www/media/new-video.mp4')
33+
args = parser.parse_args()
34+
35+
(
36+
ffmpeg_streaming
37+
.stream2file(args.input)
38+
.format('libx264')
39+
.save(args.output, progress=progress)
40+
)
41+
42+
43+
if __name__ == "__main__":
44+
sys.exit(main())

examples/dash/dash.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def per_to_time_left(percentage):
3838
def transcode_progress(per, ffmpeg):
3939
# You can update a field in your database or log it to a file
4040
# You can also create a socket connection and show a progress bar to users
41-
logging.info(ffmpeg)
41+
# logging.info(ffmpeg)
4242
sys.stdout.write("\rTranscoding...(%s%%) %s [%s%s]" % (per, per_to_time_left(per), '#' * per, '-' * (100 - per)))
4343
sys.stdout.flush()
4444

0 commit comments

Comments
 (0)