1515
1616# %%
1717# First, we'll download a video and decode some frames to tensors.
18- # These will be the input to the VideoEncoder. For more details on decoding,
18+ # These will be the input to the :class:`~torchcodec.encoders. VideoEncoder` . For more details on decoding,
1919# see :ref:`sphx_glr_generated_examples_decoding_basic_example.py`.
2020# Otherwise, skip ahead to :ref:`creating_encoder`.
2121
@@ -35,7 +35,7 @@ def play_video(encoded_bytes):
3535
3636
3737# Video source: https://www.pexels.com/video/adorable-cats-on-the-lawn-4977395/
38- # License: CC0. Author: Altaf Shah.
38+ # Author: Altaf Shah.
3939url = "https://videos.pexels.com/video-files/4977395/4977395-hd_1920_1080_24fps.mp4"
4040
4141response = requests .get (url , headers = {"User-Agent" : "" })
@@ -45,7 +45,7 @@ def play_video(encoded_bytes):
4545raw_video_bytes = response .content
4646
4747decoder = VideoDecoder (raw_video_bytes )
48- frames = decoder [: 60 ] # Get first 60 frames
48+ frames = decoder . get_frames_in_range ( 0 , 60 ). data # Get first 60 frames
4949# TODO: use float once other PR lands
5050frame_rate = int (decoder .metadata .average_fps )
5151
@@ -78,7 +78,7 @@ def play_video(encoded_bytes):
7878#
7979# :class:`~torchcodec.encoders.VideoEncoder` supports encoding frames into a
8080# file via the :meth:`~torchcodec.encoders.VideoEncoder.to_file` method, to
81- # file-like objects via the :meth:`~torchcodec.encoders.VideoEncoder.to_filelike `
81+ # file-like objects via the :meth:`~torchcodec.encoders.VideoEncoder.to_file_like `
8282# method, or to raw bytes via :meth:`~torchcodec.encoders.VideoEncoder.to_tensor`.
8383# For now we will use :meth:`~torchcodec.encoders.VideoEncoder.to_tensor`, so we
8484# can easily inspect and display the encoded video.
@@ -92,15 +92,25 @@ def play_video(encoded_bytes):
9292# round-trip encode/decode process works as expected:
9393
9494decoder_verify = VideoDecoder (encoded_frames )
95- decoded_frames = decoder_verify [:]
95+ decoded_frames = decoder_verify . get_frames_in_range ( 0 , 60 ). data
9696
9797print (f"Re-decoded video: { decoded_frames .shape = } " )
9898print (f"Original frames: { frames .shape = } " )
9999
100100# %%
101+ # .. _codec_selection:
102+ #
101103# Codec Selection
102104# ---------------
103105#
106+ # By default, the codec used is selected automatically using the file extension provided
107+ # in the ``dest`` parameter for the :meth:`~torchcodec.encoders.VideoEncoder.to_file` method,
108+ # or using the ``format`` parameter for the
109+ # :meth:`~torchcodec.encoders.VideoEncoder.to_file_like` and
110+ # :meth:`~torchcodec.encoders.VideoEncoder.to_tensor` methods.
111+ #
112+ # - For example, when encoding to MP4 format, the default codec used is ``H.264``.
113+ #
104114# The ``codec`` parameter specifies which video codec to use for encoding.
105115# You can specify either a specific codec implementation (e.g., ``"libx264"``)
106116# or a codec specification (e.g., ``"h264"``). Different codecs offer
@@ -112,18 +122,21 @@ def play_video(encoded_bytes):
112122#
113123# Let's encode the same frames using different codecs:
114124
125+ import tempfile
126+ from pathlib import Path
127+
115128# H.264 encoding
116- h264_output = "libx264_encoded .mp4"
129+ h264_output = tempfile . NamedTemporaryFile ( suffix = " .mp4", delete = False ). name
117130encoder .to_file (h264_output , codec = "libx264" )
118131
119132# H.265 encoding
120- hevc_output = "hevc_encoded .mp4"
133+ hevc_output = tempfile . NamedTemporaryFile ( suffix = " .mp4", delete = False ). name
121134encoder .to_file (hevc_output , codec = "hevc" )
122135
123136# Now let's use ffprobe to verify the codec used in the output files
124137import subprocess
125138
126- for output in [h264_output , hevc_output ]:
139+ for output , name in [( h264_output , "h264_output" ), ( hevc_output , "hevc_output" ) ]:
127140 result = subprocess .run (
128141 [
129142 "ffprobe" ,
@@ -140,9 +153,16 @@ def play_video(encoded_bytes):
140153 capture_output = True ,
141154 text = True ,
142155 )
143- print (f"Codec used in { output } : { result .stdout .strip ()} " )
156+ print (f"Codec used in { name } : { result .stdout .strip ()} " )
157+
158+ # %%
159+ # For most cases, you can simply specify the format parameter and let the FFmpeg select the default codec.
160+ # However, specifying the codec parameter is useful to select a particular codec implementation
161+ # (``libx264`` vs ``libx265``) or to have more control over the encoding behavior.
144162
145163# %%
164+ # .. _pixel_format:
165+ #
146166# Pixel Format
147167# ------------
148168#
@@ -169,6 +189,8 @@ def play_video(encoded_bytes):
169189play_video (yuv420_encoded_frames )
170190
171191# %%
192+ # .. _crf:
193+ #
172194# CRF (Constant Rate Factor)
173195# --------------------------
174196#
@@ -197,6 +219,8 @@ def play_video(encoded_bytes):
197219
198220
199221# %%
222+ # .. _preset:
223+ #
200224# Preset
201225# ------
202226#
@@ -207,25 +231,27 @@ def play_video(encoded_bytes):
207231# For example, with the commonly used H.264 codec, ``libx264`` presets include:
208232#
209233# - ``"ultrafast"`` (fastest), ``"fast"``, ``"medium"`` (default), ``"slow"``, ``"veryslow"`` (slowest, best compression).
234+ # - See additional details in the `H.264 Video Encoding Guide <https://trac.ffmpeg.org/wiki/Encode/H.264#a2.Chooseapresetandtune>`_.
210235#
211236# .. note::
212237#
213238# Not all codecs support the ``presets`` option. Use ``ffmpeg -h encoder=<codec_name>``
214239# to check available options for your selected codec.
215240#
216241
217- import os
218242# Fast encoding with a larger file size
219- fast_output = "fast_encoded .mp4"
243+ fast_output = tempfile . NamedTemporaryFile ( suffix = " .mp4", delete = False ). name
220244encoder .to_file (fast_output , codec = "libx264" , preset = "ultrafast" )
221- print (f"Size of fast encoded file: { os . path . getsize (fast_output )} bytes" )
245+ print (f"Size of fast encoded file: { Path (fast_output ). stat (). st_size } bytes" )
222246
223247# Slow encoding for a smaller file size
224- slow_output = "slow_encoded .mp4"
248+ slow_output = tempfile . NamedTemporaryFile ( suffix = " .mp4", delete = False ). name
225249encoder .to_file (slow_output , codec = "libx264" , preset = "veryslow" )
226- print (f"Size of slow encoded file: { os . path . getsize (slow_output )} bytes" )
250+ print (f"Size of slow encoded file: { Path (slow_output ). stat (). st_size } bytes" )
227251
228252# %%
253+ # .. _extra_options:
254+ #
229255# Extra Options
230256# -------------
231257#
@@ -234,7 +260,6 @@ def play_video(encoded_bytes):
234260# control of encoding settings beyond the common parameters.
235261#
236262# For example, some potential extra options for the commonly used H.264 codec, ``libx264`` include:
237- # For example, with , ``libx264``:
238263#
239264# - ``"g"`` - GOP (Group of Pictures) size / keyframe interval
240265# - ``"max_b_frames"`` - Maximum number of B-frames between I and P frames
@@ -248,7 +273,7 @@ def play_video(encoded_bytes):
248273
249274
250275# Custom GOP size and tuning
251- custom_output = "custom_encoded .mp4"
276+ custom_output = tempfile . NamedTemporaryFile ( suffix = " .mp4", delete = False ). name
252277encoder .to_file (
253278 custom_output ,
254279 codec = "libx264" ,
0 commit comments