Skip to content

Commit

Permalink
Merge pull request #10004 from nextcloud/fix-trying-to-use-an-audio-s…
Browse files Browse the repository at this point in the history
…ink-as-source

Fix trying to use an audio sink as source
  • Loading branch information
danxuliu authored Jul 19, 2023
2 parents 4540b39 + 58de73c commit 80ec121
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
5 changes: 3 additions & 2 deletions recording/src/nextcloud/talk/recording/Benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ def run(self, args):
self._display.start()

# Start new audio sink for the audio output of the player.
self._audioModuleIndex, audioSinkIndex = newAudioSink("nextcloud-talk-recording-benchmark")
self._audioModuleIndex, audioSinkIndex, audioSourceIndex = newAudioSink("nextcloud-talk-recording-benchmark")
audioSinkIndex = str(audioSinkIndex)
audioSourceIndex = str(audioSourceIndex)

env = self._display.env()
env['PULSE_SINK'] = audioSinkIndex
Expand All @@ -166,7 +167,7 @@ def run(self, args):
recorderArgumentsBuilder.setFfmpegOutputAudio(args.audio_args.split())
recorderArgumentsBuilder.setFfmpegOutputVideo(args.video_args.split())
recorderArgumentsBuilder.setExtension(f".{extension}")
self._recorderArguments = recorderArgumentsBuilder.getRecorderArguments(status, self._display.new_display_var, audioSinkIndex, args.width, args.height, extensionlessFileName)
self._recorderArguments = recorderArgumentsBuilder.getRecorderArguments(status, self._display.new_display_var, audioSourceIndex, args.width, args.height, extensionlessFileName)

self._fileName = self._recorderArguments[-1]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ def __init__(self):
self._ffmpegOutputVideo = None
self._extension = None

def getRecorderArguments(self, status, displayId, audioSinkIndex, width, height, extensionlessOutputFileName):
def getRecorderArguments(self, status, displayId, audioSourceIndex, width, height, extensionlessOutputFileName):
"""
Returns the list of arguments to start the recorder process.
:param status: whether to record audio and video or only audio.
:param displayId: the ID of the display that the browser is running in.
:param audioSinkIndex: the index of the sink for the browser audio output.
:param audioSourceIndex: the index of the source for the browser audio
output.
:param width: the width of the display and the recording.
:param height: the height of the display and the recording.
:param extensionlessOutputFileName: the file name for the recording, without
Expand All @@ -51,7 +52,7 @@ def getRecorderArguments(self, status, displayId, audioSinkIndex, width, height,
"""

ffmpegCommon = ['ffmpeg', '-loglevel', 'level+warning', '-n']
ffmpegInputAudio = ['-f', 'pulse', '-i', audioSinkIndex]
ffmpegInputAudio = ['-f', 'pulse', '-i', audioSourceIndex]
ffmpegInputVideo = ['-f', 'x11grab', '-draw_mouse', '0', '-video_size', f'{width}x{height}', '-i', displayId]
ffmpegOutputAudio = self.getFfmpegOutputAudio()
ffmpegOutputVideo = self.getFfmpegOutputVideo()
Expand Down
27 changes: 20 additions & 7 deletions recording/src/nextcloud/talk/recording/Service.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,18 @@ def newAudioSink(baseSinkName):
Start new audio sink for the audio output of the browser.
Each browser instance uses its own sink that will then be captured by the
recorder. Otherwise several browsers would use the same default sink, and
their audio output would be mixed.
recorder (using the monitor of that sink as the source). Otherwise several
browsers would use the same default sink, and their audio output would be
mixed.
The sink is created by loading a null sink module. This module needs to be
unloaded once the sink is no longer needed to remove it.
unloaded once the sink is no longer needed to remove it (which also removes
the monitor of that sink).
:param baseSinkName: the base name for the sink; it is expected to have been
sanitized and to contain only alpha-numeric characters.
:return: a tuple with the module index and the sink index, both as ints.
:return: a tuple with the module index, the sink index and the source index
(the monitor of the sink), all as ints.
"""

# A random value is appended to the base sink name to "ensure" that there
Expand Down Expand Up @@ -83,7 +86,16 @@ def newAudioSink(baseSinkName):
if not sinkIndex:
raise Exception(f"New audio sink {sinkName} not found ({sinkList})")

return moduleIndex, sinkIndex
sourceIndex = None
sourceList = pacmd.source_list()
for source in sourceList:
if source.monitor_of_sink == sinkIndex:
sourceIndex = source.index

if not sourceIndex:
raise Exception(f"Audio source (monitor) of sink {sinkName} not found ({sourceList})")

return moduleIndex, sinkIndex, sourceIndex

def processLog(loggerName, pipe, level = logging.INFO):
"""
Expand Down Expand Up @@ -180,8 +192,9 @@ def start(self, actorType, actorId):
raise Exception("Display started after recording was stopped")

# Start new audio sink for the audio output of the browser.
self._audioModuleIndex, audioSinkIndex = newAudioSink(f"{sanitizedBackend}-{self.token}")
self._audioModuleIndex, audioSinkIndex, audioSourceIndex = newAudioSink(f"{sanitizedBackend}-{self.token}")
audioSinkIndex = str(audioSinkIndex)
audioSourceIndex = str(audioSourceIndex)

if self._stopped.is_set():
raise Exception("Audio sink started after recording was stopped")
Expand Down Expand Up @@ -210,7 +223,7 @@ def start(self, actorType, actorId):
extensionlessFileName = f'{fullDirectory}/Recording {datetime.now().strftime("%Y-%m-%d %H-%M-%S")}'

recorderArgumentsBuilder = RecorderArgumentsBuilder()
recorderArguments = recorderArgumentsBuilder.getRecorderArguments(self.status, self._display.new_display_var, audioSinkIndex, width, height, extensionlessFileName)
recorderArguments = recorderArgumentsBuilder.getRecorderArguments(self.status, self._display.new_display_var, audioSourceIndex, width, height, extensionlessFileName)

self._fileName = recorderArguments[-1]

Expand Down

0 comments on commit 80ec121

Please sign in to comment.