ntgcalls - Native Telegram Calls Streaming
ntgcalls is a Python library that provides a native implementation for handling real-time audio and video streams within Telegram calls. It acts as the low-level backend for `pytgcalls`, enabling seamless streaming of media directly into Telegram voice chats. The library currently supports Python 3.10+ and releases new versions to maintain compatibility with `pytgcalls` and `pyrogram`, typically following their release cycles, with the current version being 2.1.0.
Common errors
-
FileNotFoundError: [Errno 2] No such file or directory: 'ffmpeg'
cause `ffmpeg` is not installed on the system or not in the system's PATH, which ntgcalls uses internally for media processing.fixInstall `ffmpeg` for your operating system and ensure its executable is discoverable by your system's PATH environment variable. -
RuntimeWarning: coroutine 'VideoStream.start' was never awaited
cause An asynchronous method, such as `stream.start()`, was called without the `await` keyword in an asynchronous context.fixEnsure all calls to async methods are prefixed with `await`, e.g., `await video_stream.start()`. -
TypeError: object VideoStream is not awaitable
cause Attempting to `await` a `VideoStream` object directly when it should be iterated asynchronously to get frames, or a method call was intended.fixIf you intend to iterate for frames, use `async for frame in video_stream:`. If you meant to call a method, ensure it's `await video_stream.method()`. -
ImportError: cannot import name 'VideoStream' from 'ntgcalls'
cause An older or incompatible version of `ntgcalls` is installed, or the import path for `VideoStream` (or `AudioStream`) has changed between versions.fixEnsure `ntgcalls` is updated to the latest version (`pip install --upgrade ntgcalls`) and verify the correct import path from the official documentation.
Warnings
- gotcha ntgcalls relies heavily on `ffmpeg` for all media processing. `ffmpeg` must be installed on your system and accessible via the system PATH, otherwise streams will fail to initialize with an `OSError` or `FileNotFoundError`.
- gotcha All operations in ntgcalls are asynchronous. Misusing synchronous calls or forgetting `await` before calling an asynchronous method will result in `RuntimeWarning` (coroutine was never awaited) or `TypeError`.
- breaking Ensure `ntgcalls`, `pytgcalls`, and `pyrogram` versions are compatible. New major releases of `pytgcalls` or `pyrogram` may introduce API changes that require an `ntgcalls` update to maintain functionality.
- gotcha Streams must be explicitly started with `await stream.start()` and stopped with `await stream.stop()` to properly manage underlying resources (like `ffmpeg` processes) and prevent resource leaks.
- breaking ntgcalls requires Python 3.10 or higher. Running on older Python versions will lead to `SyntaxError` or import failures due to its reliance on modern async features and type hints.
Install
-
pip install ntgcalls
Imports
- VideoStream
from ntgcalls import VideoStream
- AudioStream
from ntgcalls import AudioStream
- VideoFrame
from ntgcalls.types import VideoFrame
- AudioFrame
from ntgcalls.types import AudioFrame
Quickstart
import asyncio
from ntgcalls import VideoStream
import os
async def main():
# To run this quickstart, you MUST have ffmpeg installed and available in your system's PATH.
# You also need a video file for input. Replace 'your_video.mp4' with an actual path.
# For quick testing, you can set an environment variable: export VIDEO_PATH="/path/to/your_video.mp4"
video_input_path = os.environ.get('VIDEO_PATH', 'test_video.mp4') # Use an actual video file path
if not os.path.exists(video_input_path):
print(f"Warning: Video file '{video_input_path}' not found.")
print("Please ensure you have a video file for input and ffmpeg is installed.")
print("You can set the VIDEO_PATH environment variable to point to your video file.")
print("Example: `export VIDEO_PATH=~/Videos/my_test.mp4` then run the script.")
return
print(f"Attempting to process video stream from: {video_input_path}")
try:
# Create a VideoStream instance from a file path
# ntgcalls uses ffmpeg internally to process this file
video_stream = VideoStream(video_input_path)
# Start the video stream. This initializes the underlying ffmpeg process.
await video_stream.start()
print("Video stream started. Reading a few frames...")
frame_count = 0
# Iterate over the stream to get video frames
async for frame in video_stream:
if frame:
print(f"Got video frame {frame_count}: {frame.data_length} bytes, {frame.width}x{frame.height}")
frame_count += 1
if frame_count >= 3: # Read a few frames then stop for demonstration
print("Read 3 frames, stopping for quickstart demonstration.")
break
else:
# This might happen if stream ends or no frames are ready yet
print("No video frame available yet or stream ended.")
break
if frame_count == 0:
print("No frames were successfully read. Check ffmpeg installation and video input path.")
# Stop the video stream and release resources
await video_stream.stop()
print("Video stream stopped.")
except FileNotFoundError as e:
print(f"Error: {e}. This often means ffmpeg is not found or the video file is incorrect.")
print("Please ensure ffmpeg is installed and accessible in your system's PATH.")
except Exception as e:
print(f"An unexpected error occurred: {e}")
print("Ensure your video file is valid and ffmpeg can process it.")
if __name__ == "__main__":
asyncio.run(main())