Skip to content

Commit 2030d67

Browse files
committed
Review fixes
1 parent 7028ae2 commit 2030d67

File tree

3 files changed

+32
-13
lines changed

3 files changed

+32
-13
lines changed

.formatter.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Used by "mix format"
22
[
3-
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
3+
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
4+
import_deps: [:membrane_core]
45
]

lib/ex_webrtc_recorder/converter.ex

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ defmodule ExWebRTC.Recorder.Converter do
6161
6262
* `:threads` - How many threads to use. Unlimited by default.
6363
* `:bitrate` - Video bitrate the VP8 encoder shall strive for. `#{@default_reencode_bitrate}` by default.
64-
* `:gop_size` - Keyframe interval. #{@default_reencode_gop_size} by default.
64+
* `:gop_size` - Keyframe interval. `#{@default_reencode_gop_size}` by default.
6565
* `:cues_to_front` - Whether the muxer should put MKV Cues element at the front of the file,
66-
to aid with seeking e.g. when streaming the result file. #{@default_reencode_cues_to_front} by default.
66+
to aid with seeking e.g. when streaming the result file. `#{@default_reencode_cues_to_front}` by default.
6767
"""
6868
@type reencode_ctx :: %{
6969
optional(:threads) => pos_integer(),
@@ -92,6 +92,9 @@ defmodule ExWebRTC.Recorder.Converter do
9292
Increasing this value may help with "Decoded late RTP packet" warnings,
9393
but keep in mind that larger values slow the conversion process considerably.
9494
* `:reencode_ctx` - If passed, Converter will reencode the video using FFmpeg.
95+
The keyframe interval of video tracks sent over WebRTC may vary, so this is helpful when
96+
you want to generate additional ones, to facilitate accurate seeking in the result file during playback.
97+
Keep in mind that reenncoding is slow and resource-intensive.
9598
See `t:reencode_ctx/0` for more info.
9699
"""
97100
@type option ::
@@ -240,6 +243,10 @@ defmodule ExWebRTC.Recorder.Converter do
240243
reorder_buffer_size,
241244
reencode_ctx
242245
) do
246+
# What's happening here:
247+
# 1. Read tracks
248+
# 2. Convert tracks to WEBM files
249+
# 3. Mux WEBM files into a single file
243250
stream_map =
244251
Enum.reduce(manifest, %{}, fn {_id, track}, stream_map ->
245252
%{
@@ -264,11 +271,10 @@ defmodule ExWebRTC.Recorder.Converter do
264271
case kind do
265272
:video ->
266273
rid_map = filter_rids(rid_map, rid_allowed?)
267-
268274
get_video_track_contexts(rid_map, packets)
269275

270276
:audio ->
271-
%{nil: get_audio_track_context(packets |> Map.values() |> hd())}
277+
get_audio_track_context(packets)
272278
end
273279

274280
stream_id = List.first(streams)
@@ -289,10 +295,14 @@ defmodule ExWebRTC.Recorder.Converter do
289295
video_stream = make_stream(self(), :video)
290296
audio_stream = make_stream(self(), :audio)
291297

298+
# FIXME: Possible RC here: when the pipeline playback starts, the `Stream`s will start sending
299+
# `{:demand, kind, self()}` messages to this process.
300+
# There's no guarantee we'll start listening for these messages (in `emit_packets/3`) soon enough,
301+
# so we may reach a deadlock.
302+
# For now, it seems to work just fine, though.
292303
{:ok, _sup, pid} = Pipeline.start_link(video_stream, audio_stream, output_file)
293304
Process.monitor(pid)
294305

295-
# FIXME: Possible RC here?
296306
emit_packets(pid, video_ctx.packets, audio_ctx.packets)
297307

298308
FFmpeg.combine_av!(
@@ -401,12 +411,12 @@ defmodule ExWebRTC.Recorder.Converter do
401411
end
402412
end
403413

404-
defp get_audio_track_context(packets) do
414+
defp get_audio_track_context(%{nil: packets}) do
405415
{:ok, depayloader} = Depayloader.new(@audio_codec_params)
406416

407417
start_time = get_start_time(packets, depayloader)
408418

409-
%{packets: packets, start_time: start_time}
419+
%{nil: %{packets: packets, start_time: start_time}}
410420
end
411421

412422
# Returns the timestamp (in milliseconds) at which the first frame was received

lib/ex_webrtc_recorder/converter/pipeline.ex

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
defmodule ExWebRTC.Recorder.Converter.Pipeline do
2+
# This pipeline:
3+
# - takes the sorted RTP packets from Converter,
4+
# - depayloads the VP8/Opus media within,
5+
# - and dumps them into two separate WEBM files.
6+
#
7+
# The result file is then generated using FFmpeg.
8+
# We have to do it this way, because at the moment `Membrane.Matroska.Muxer` ignores the difference in PTS
9+
# of the audio and video tracks, which means we're unable to synchronize them using only Membrane.
10+
211
defmodule Source do
312
@moduledoc false
413
use Membrane.Source
514

6-
def_options(
7-
stream: [
8-
spec: Enumerable.t()
9-
]
10-
)
15+
def_options stream: [
16+
spec: Enumerable.t()
17+
]
1118

1219
def_output_pad(:output, accepted_format: Membrane.RTP, flow_control: :manual)
1320

@@ -55,6 +62,7 @@ defmodule ExWebRTC.Recorder.Converter.Pipeline do
5562
@impl true
5663
def handle_init(_ctx, opts) do
5764
# TODO: Support codecs other than VP8/Opus
65+
# TODO: Use a single muxer + sink once `Membrane.Matroska.Muxer` supports synchronizing AV
5866
spec = [
5967
child(:video_source, %Source{stream: opts.video_stream})
6068
|> child(:video_depayloader, %Membrane.RTP.DepayloaderBin{

0 commit comments

Comments
 (0)