Skip to content

Commit

Permalink
⚡️ StreamGear: Updated support of Stream Copy in Single Source mode. (F…
Browse files Browse the repository at this point in the history
…ixes #396)

- ♻️ Ignore the stream copy parameter if Real-time Frames Mode or Custom Streams are enabled, and log appropriate warnings.
- ⚡️Updated the handling of the `-acodec` parameter:
     - Use the default `aac` codec for Custom Streams.
     - Use stream copy (`-acodec copy`) for the input video's audio stream if Custom Streams are not enabled.
- ♻️ Refactor the handling of the `-livestream` parameter to ensure it is only enabled for the Real-time Frames Mode.
- ♻️ Refactor the video and audio bitrate assignment to skip the assignment when stream copy is enabled.
- 🔊 Updated log message for `-clear_prev_assets` parameter.
- ✏️ Fix a typo in comments.

Docs:
- 📝 Add a new tip box explaining the benefits of using stream copy (`-vcodec copy`) in the Single Source Mode for faster transcoding of HLS/DASH streams.
- 💬 Highlight the limitations of stream copy, such as incompatibility with Real-time Frames Mode and Custom Streams, which require re-encoding of frames.
- 💬 Clarify that the audio stream copy (`-acodec copy`) is automatically applied when using the input video's audio stream.
- 🎨 Fixed various issues like typos, formatting errors, code highlighting issues, and grammar inconsistencies.
  • Loading branch information
abhiTronix committed Jun 9, 2024
1 parent 8667e5e commit 49cc04f
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 42 deletions.
3 changes: 0 additions & 3 deletions docs/gears/pigear/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,18 @@ Following is the bare-minimum code you need to get started with PiGear API:
=== ":material-linux: Linux"

```sh
# path to file
export LIBCAMERA_LOG_LEVELS=2
```

=== ":fontawesome-brands-windows: Windows (Powershell)"

```powershell
# path to file
$Env:LIBCAMERA_LOG_LEVELS=2
```

=== ":material-apple: MacOS"
```sh
# path to file
export LIBCAMERA_LOG_LEVELS=2
```

Expand Down
17 changes: 12 additions & 5 deletions docs/gears/streamgear/params.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ StreamGear API provides some exclusive internal parameters to easily generate St
# set video source as `/home/foo/bar.mp4`
stream_params = {"-video_source": "/home/foo/bar.mp4"}
```

* **Video URL**: Valid URL of a network video stream as follows:

!!! danger "Ensure the given video URL uses a protocol supported by the installed FFmpeg _(verify with `ffmpeg -protocols` terminal command)_."
Expand Down Expand Up @@ -269,7 +270,7 @@ StreamGear API provides some exclusive internal parameters to easily generate St

 

* **`-livestream`** _(bool)_: ***(optional)*** specifies whether to enable **Low-latency Live-Streaming :material-video-wireless-outline:** in Real-time Frames Mode only, where chunks will contain information for new frames only and forget previous ones, or not. The default value is `False`. It can be used as follows:
* **`-livestream`** _(bool)_: ***(optional)*** specifies whether to enable **Low-latency Live-Streaming :material-video-wireless-outline:** in [**Real-time Frames Mode**](../rtfm/overview) only, where chunks will contain information for new frames only and forget previous ones, or not. The default value is `False`. It can be used as follows:

!!! warning "The `-livestream` optional parameter is **NOT** supported in [Single-Source mode](../ssm/overview)."

Expand Down Expand Up @@ -338,9 +339,9 @@ StreamGear API provides some exclusive internal parameters to easily generate St

 

* **`-clear_prev_assets`** _(bool)_: ***(optional)*** This parameter specifies whether to force-delete any previous copies of StreamGear assets _(i.e., manifest (`mpd`), playlist (`mu38`), and streaming chunks (`.m4s`), etc. files)_ present at the path specified by the [`output`](#output) parameter. The default value is `False`. It can be used as follows:
* **`-clear_prev_assets`** _(bool)_: ***(optional)*** This parameter specifies whether to remove/delete all previous copies of StreamGear assets files for selected [`format`](#format) _(i.e., manifest (`mpd`) in DASH, playlist (`mu38`) in HLS, and respective streaming chunks (`.ts`,`.m4s`), etc.)_ present at the path specified by the [`output`](#output) parameter. The default value is `False`. It can be enabled as follows:

!!! info "Additional segments _(such as `.webm`, `.mp4` chunks)_ are also cleared automatically."
!!! info "Additional segments _(such as `.webm`, `.mp4` chunks)_ are also removed automatically."

```python
# delete all previous assets
Expand Down Expand Up @@ -381,9 +382,13 @@ stream_params = {"-vcodec":"libx264", "-crf": 0, "-preset": "fast", "-tune": "ze

All encoders and decoders compiled with the FFmpeg in use are supported by the StreamGear API. You can check the compiled encoders by running the following command in your terminal:

!!! warning "Stream copy (`-vcodec copy`) is not compatible with Real-time Frames Mode as this mode requires re-encoding of incoming frames."
???+ tip "Faster Transcoding with Stream Copy in Single Source Mode"

For faster transcoding of input video, utilize Stream copy (`-vcodec copy`) as the input video encoder in the [**Single-Source Mode**](../ssm/overview) for creating HLS/DASH chunks of the primary stream efficiently. However, consider the following points:

!!! info "Similarly, supported audio/video demuxers and filters depend on the FFmpeg binaries in use."
- :warning: Stream copy is **NOT** compatible with [**Real-time Frames Mode**](../rtfm/overview), as this mode necessitates re-encoding of incoming frames. Therefore, the `-vcodec copy` parameter will be ignored.
- :warning: Stream copying **NOT** compatible with Custom Streams ([`-streams`](#a-exclusive-parameters)), which also require re-encoding for each additional stream. Consequently, the `-vcodec copy` parameter will be ignored.
- When using the audio stream from the input video, the Audio Stream copy (`-acodec copy`) encoder will be automatically applied.

```sh
# for checking encoder
Expand All @@ -392,6 +397,8 @@ ffmpeg -encoders # use `ffmpeg.exe -encoders` on windows
ffmpeg -decoders # use `ffmpeg.exe -decoders` on windows
```

!!! info "Similarly, supported audio/video demuxers and filters depend on the FFmpeg binaries in use."

 

## **`logging`**
Expand Down
14 changes: 6 additions & 8 deletions docs/gears/streamgear/rtfm/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ limitations under the License.
- [x] StreamGear API **MUST** requires FFmpeg executables for its core operations. Follow these dedicated [Platform specific Installation Instructions ➶](../../ffmpeg_install/) for its installation. API will throw **RuntimeError**, if it fails to detect valid FFmpeg executables on your system.
- [x] In this mode, ==API by default generates a primary stream _(at the index `0`)_ of same resolution as the input frames and at default framerate[^1].==
- [x] In this mode, API **DOES NOT** automatically maps video-source audio to generated streams. You need to manually assign separate audio-source through [`-audio`](../../params/#a-exclusive-parameters) attribute of `stream_params` dictionary parameter.
- [x] In this mode, Stream copy (`-vcodec copy`) is not compatible as this mode requires re-encoding of incoming frames.
- [x] In this mode, Stream copy (`-vcodec copy`) encoder is unsupported as it requires re-encoding of incoming frames.
- [x] Always use `close()` function at the very end of the main code.

???+ danger "DEPRECATION NOTICES for `v0.3.3` and above"
??? danger "DEPRECATION NOTICES for `v0.3.3` and above"

- [ ] The `terminate()` method in StreamGear is now deprecated and will be removed in a future release. Developers should use the new [`close()`](../../../../bonus/reference/streamgear/#vidgear.gears.streamgear.StreamGear.close) method instead, as it offers a more descriptive name, similar to the WriteGear API, for safely terminating StreamGear processes.
- [ ] The `rgb_mode` parameter in [`stream()`](../../../bonus/reference/streamgear/#vidgear.gears.streamgear.StreamGear.stream) method, which earlier used to support RGB frames in Real-time Frames Mode is now deprecated, and will be removed in a future version. Only BGR format frames will be supported going forward. Please update your code to handle BGR format frames.
Expand Down Expand Up @@ -515,7 +515,7 @@ To generate Secondary Streams, add each desired resolution and bitrate/framerate

=== "DASH"

```python linenums="1" hl_lines="12-14"
```python linenums="1" hl_lines="11-15"
# import required libraries
from vidgear.gears import CamGear
from vidgear.gears import StreamGear
Expand Down Expand Up @@ -571,7 +571,7 @@ To generate Secondary Streams, add each desired resolution and bitrate/framerate

=== "HLS"

```python linenums="1" hl_lines="12-14"
```python linenums="1" hl_lines="11-15"
# import required libraries
from vidgear.gears import CamGear
from vidgear.gears import StreamGear
Expand Down Expand Up @@ -1038,11 +1038,9 @@ In this example, we will be using `h264_vaapi` as our Hardware Encoder and speci

!!! danger "This example is just conveying the idea of how to use FFmpeg's hardware encoders with the StreamGear API in Real-time Frames Mode, which MAY OR MAY NOT suit your system. Please use suitable parameters based on your supported system and FFmpeg configurations only."

!!! warning "Stream copy (`-vcodec copy`) is not compatible with this Mode as it requires re-encoding of incoming frames."
???+ info "Checking VAAPI Support for Hardware Encoding"

??? info "Check VAAPI support"

To use `h264_vaapi` encoder, remember to check if its available and your FFmpeg compiled with VAAPI support. You can easily do this by executing following one-liner command in your terminal, and observing if output contains something similar as follows:
To use **VAAPI** (Video Acceleration API) as a hardware encoder in this example, follow these steps to ensure your FFmpeg supports VAAPI:

```sh
ffmpeg -hide_banner -encoders | grep vaapi
Expand Down
12 changes: 9 additions & 3 deletions docs/gears/streamgear/ssm/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@ limitations under the License.
- [x] In this mode, if input video-source _(i.e. `-video_source`)_ contains any audio stream/channel, then it automatically gets mapped to all generated streams.
- [x] Always use `close()` function at the very end of the main code.

???+ danger "DEPRECATION NOTICES for `v0.3.3` and above"
??? danger "DEPRECATION NOTICES for `v0.3.3` and above"

- [ ] The `terminate()` method in StreamGear is now deprecated and will be removed in a future release. Developers should use the new [`close()`](../../../../bonus/reference/streamgear/#vidgear.gears.streamgear.StreamGear.close) method instead, as it offers a more descriptive name, similar to the WriteGear API, for safely terminating StreamGear processes.
- [ ] The [`-livestream`](../../params/#a-exclusive-parameters) optional parameter is NOT supported in this Single-Source Mode.

??? tip "Faster Transcoding of Primary Stream with Stream Copy in Single Source Mode"

For faster transcoding of input video in this mode, utilize Stream copy (`-vcodec copy`) as the input video encoder for creating HLS/DASH chunks of the primary stream efficiently. However, consider the following points:

- :warning: Stream copying **NOT** compatible with Custom Streams ([`-streams`](../../params/#a-exclusive-parameters)), which require re-encoding for each additional stream. Therefore, the `-vcodec copy` parameter will be ignored.
- When using the audio stream from the input video, the Audio Stream copy (`-acodec copy`) encoder will be automatically applied.

!!! example "After going through following Usage Examples, Checkout more of its advanced configurations [here ➶](../../../help/streamgear_ex/)"

Expand Down Expand Up @@ -106,7 +112,7 @@ To generate Secondary Streams, add each desired resolution and bitrate/framerate

=== "DASH"

```python linenums="1" hl_lines="6-12"
```python linenums="1" hl_lines="7-12"
# import required libraries
from vidgear.gears import StreamGear

Expand All @@ -130,7 +136,7 @@ To generate Secondary Streams, add each desired resolution and bitrate/framerate

=== "HLS"

```python linenums="1" hl_lines="6-12"
```python linenums="1" hl_lines="7-12"
# import required libraries
from vidgear.gears import StreamGear

Expand Down
56 changes: 33 additions & 23 deletions vidgear/gears/streamgear.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,16 +214,18 @@ def __init__(
if isinstance(clear_assets, bool):
self.__clear_assets = clear_assets
# log if clearing assets is enabled
clear_assets and logger.debug(
"Previous StreamGear API assets will be deleted in this run."
clear_assets and logger.info(
"The `-clear_prev_assets` parameter is enabled successfully. All previous StreamGear API assets for `{}` format will be removed for this run.".format(
self.__format.upper()
)
)
else:
# reset improper values
self.__clear_assets = False

# handle whether to livestream?
livestreaming = self.__params.pop("-livestream", False)
if isinstance(livestreaming, bool):
if isinstance(livestreaming, bool) and livestreaming:
# NOTE: `livestream` is only available with real-time mode.
self.__livestreaming = livestreaming if not (self.__video_source) else False
if self.__video_source:
Expand Down Expand Up @@ -471,7 +473,8 @@ def __PreProcess(self, channels=0, rgb=False):
# in Real-time Frames Mode
output_parameters["-vcodec"] = (
default_codec
if output_vcodec == "copy" and not (self.__video_source)
if output_vcodec == "copy"
and (not (self.__video_source) or "-streams" in self.__params)
else output_vcodec
)
# enforce compatibility with stream copy
Expand All @@ -482,7 +485,10 @@ def __PreProcess(self, channels=0, rgb=False):
else:
# log warnings if stream copy specified in Real-time Frames Mode
not (self.__video_source) and logger.error(
"Stream copy is not compatible with Real-time Frames Mode as it requires re-encoding of incoming frames. Discarding the `-vcodec copy` parameter!"
"Stream copy is not compatible with Real-time Frames Mode as it require re-encoding of incoming frames. Discarding the `-vcodec copy` parameter!"
)
("-streams" in self.__params) and logger.error(
"Stream copying is incompatible with Custom Streams as it require re-encoding for each additional stream. Discarding the `-vcodec copy` parameter!"
)
# log warnings for these parameters
self.__params.pop("-vf", False) and logger.warning(
Expand Down Expand Up @@ -532,9 +538,7 @@ def __PreProcess(self, channels=0, rgb=False):
)
] = self.__audio
# assign audio codec
output_parameters["-acodec"] = self.__params.pop(
"-acodec", "aac" if isinstance(self.__audio, list) else "copy"
)
output_parameters["-acodec"] = self.__params.pop("-acodec", "aac")
output_parameters["a_bitrate"] = bitrate # temporary handler
output_parameters["-core_audio"] = (
["-map", "1:a:0"] if self.__format == "dash" else []
Expand All @@ -549,12 +553,14 @@ def __PreProcess(self, channels=0, rgb=False):
elif self.__video_source:
bitrate = validate_audio(self.__ffmpeg, source=self.__video_source)
if bitrate:
logger.info("Input Video's audio source will be used for this run.")
logger.info("Input video's audio source will be used for this run.")
# assign audio codec
output_parameters["-acodec"] = (
"aac" if self.__format == "hls" else "copy"
output_parameters["-acodec"] = self.__params.pop(
"-acodec",
"aac" if ("-streams" in self.__params) else "copy",
)
output_parameters["a_bitrate"] = bitrate # temporary handler
if output_parameters["-acodec"] != "copy":
output_parameters["a_bitrate"] = bitrate # temporary handler
else:
logger.info(
"No valid audio source available in the input video. Disabling audio while generating streams."
Expand Down Expand Up @@ -602,7 +608,7 @@ def __PreProcess(self, channels=0, rgb=False):
), "[StreamGear:ERROR] :: `{}` stream cannot be initiated properly!".format(
self.__format.upper()
)
# Finally start FFmpef pipline and process everything
# Finally start FFmpeg pipeline and process everything
self.__Build_n_Execute(process_params[0], process_params[1])

def __handle_streams(self, input_params, output_params):
Expand Down Expand Up @@ -652,22 +658,26 @@ def __handle_streams(self, input_params, output_params):
if "-s:v:0" in self.__params:
# prevent duplicates
del self.__params["-s:v:0"]
output_params["-s:v:0"] = "{}x{}".format(self.__inputwidth, self.__inputheight)
if output_params["-vcodec"] != "copy":
output_params["-s:v:0"] = "{}x{}".format(
self.__inputwidth, self.__inputheight
)
# assign default output video-bitrate
if "-b:v:0" in self.__params:
# prevent duplicates
del self.__params["-b:v:0"]
output_params["-b:v:0"] = (
str(
get_video_bitrate(
int(self.__inputwidth),
int(self.__inputheight),
self.__sourceframerate,
bpp,
if output_params["-vcodec"] != "copy":
output_params["-b:v:0"] = (
str(
get_video_bitrate(
int(self.__inputwidth),
int(self.__inputheight),
self.__sourceframerate,
bpp,
)
)
+ "k"
)
+ "k"
)

# assign default output audio-bitrate
if "-b:a:0" in self.__params:
Expand Down

0 comments on commit 49cc04f

Please sign in to comment.