feat: Support for capturing audio for chrome tab. (#158)

* feat: Support for capturing audio for chrome tab.

* Update code comments.
This commit is contained in:
CloudWebRTC
2022-09-07 15:15:11 +08:00
committed by GitHub
parent 7c01c115d8
commit cbdfa634a3
7 changed files with 75 additions and 7 deletions
+3
View File
@@ -83,3 +83,6 @@ _build
# FVM # FVM
.fvm/ .fvm/
# flutter web
lib/generated_plugin_registrant.dart
+1 -1
View File
@@ -169,7 +169,7 @@ class _ControlsWidgetState extends State<ControlsWidget> {
print('could not publish video: $e'); print('could not publish video: $e');
} }
} }
await participant.setScreenShareEnabled(true); await participant.setScreenShareEnabled(true, captureScreenAudio: true);
} }
void _disableScreenShare() async { void _disableScreenShare() async {
+26 -3
View File
@@ -15,6 +15,7 @@ import '../publication/local.dart';
import '../track/local/audio.dart'; import '../track/local/audio.dart';
import '../track/local/local.dart'; import '../track/local/local.dart';
import '../track/local/video.dart'; import '../track/local/video.dart';
import '../track/options.dart';
import '../types/other.dart'; import '../types/other.dart';
import '../types/participant_permissions.dart'; import '../types/participant_permissions.dart';
import '../types/video_dimensions.dart'; import '../types/video_dimensions.dart';
@@ -283,14 +284,17 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
} }
/// Shortcut for publishing a [TrackSource.screenShareVideo] /// Shortcut for publishing a [TrackSource.screenShareVideo]
Future<LocalTrackPublication?> setScreenShareEnabled(bool enabled) async { Future<LocalTrackPublication?> setScreenShareEnabled(bool enabled,
return setSourceEnabled(TrackSource.screenShareVideo, enabled); {bool? captureScreenAudio}) async {
return setSourceEnabled(TrackSource.screenShareVideo, enabled,
captureScreenAudio: captureScreenAudio);
} }
/// A convenience method to publish a track for a specific [TrackSource]. /// A convenience method to publish a track for a specific [TrackSource].
/// This is the recommended method to publish tracks. /// This is the recommended method to publish tracks.
Future<LocalTrackPublication?> setSourceEnabled( Future<LocalTrackPublication?> setSourceEnabled(
TrackSource source, bool enabled) async { TrackSource source, bool enabled,
{bool? captureScreenAudio}) async {
logger.fine('setSourceEnabled(source: $source, enabled: $enabled)'); logger.fine('setSourceEnabled(source: $source, enabled: $enabled)');
final publication = getTrackPublicationBySource(source); final publication = getTrackPublicationBySource(source);
if (publication != null) { if (publication != null) {
@@ -314,6 +318,25 @@ class LocalParticipant extends Participant<LocalTrackPublication> {
room.roomOptions.defaultAudioCaptureOptions); room.roomOptions.defaultAudioCaptureOptions);
return await publishAudioTrack(track); return await publishAudioTrack(track);
} else if (source == TrackSource.screenShareVideo) { } else if (source == TrackSource.screenShareVideo) {
/// When capturing chrome table audio, we can't capture audio/video
/// track separately, it has to be returned once in getDisplayMedia,
/// so we publish it twice here, but only return videoTrack to user.
if (captureScreenAudio != null) {
final tracks = await LocalVideoTrack.createScreenShareTracksWithAudio(
ScreenShareCaptureOptions(
captureScreenAudio: captureScreenAudio));
LocalTrackPublication<LocalVideoTrack>? publication;
for (final track in tracks) {
if (track is LocalVideoTrack) {
publication = await publishVideoTrack(track);
} else if (track is LocalAudioTrack) {
await publishAudioTrack(track);
}
}
/// just return the video track publication
return publication;
}
final track = await LocalVideoTrack.createScreenShareTrack( final track = await LocalVideoTrack.createScreenShareTrack(
room.roomOptions.defaultScreenShareCaptureOptions); room.roomOptions.defaultScreenShareCaptureOptions);
return await publishVideoTrack(track); return await publishVideoTrack(track);
+4 -2
View File
@@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import 'package:meta/meta.dart';
import '../../proto/livekit_models.pb.dart' as lk_models; import '../../proto/livekit_models.pb.dart' as lk_models;
import '../../types/other.dart'; import '../../types/other.dart';
@@ -15,7 +16,8 @@ class LocalAudioTrack extends LocalTrack
covariant AudioCaptureOptions currentOptions; covariant AudioCaptureOptions currentOptions;
// private constructor // private constructor
LocalAudioTrack._( @internal
LocalAudioTrack(
String name, String name,
TrackSource source, TrackSource source,
rtc.MediaStream stream, rtc.MediaStream stream,
@@ -36,7 +38,7 @@ class LocalAudioTrack extends LocalTrack
options ??= const AudioCaptureOptions(); options ??= const AudioCaptureOptions();
final stream = await LocalTrack.createStream(options); final stream = await LocalTrack.createStream(options);
return LocalAudioTrack._( return LocalAudioTrack(
'', '',
TrackSource.microphone, TrackSource.microphone,
stream, stream,
+3 -1
View File
@@ -119,7 +119,9 @@ abstract class LocalTrack extends Track {
final constraints = <String, dynamic>{ final constraints = <String, dynamic>{
'audio': options is AudioCaptureOptions 'audio': options is AudioCaptureOptions
? options.toMediaConstraintsMap() ? options.toMediaConstraintsMap()
: false, : options is ScreenShareCaptureOptions
? (options).captureScreenAudio
: false,
'video': options is VideoCaptureOptions 'video': options is VideoCaptureOptions
? options.toMediaConstraintsMap() ? options.toMediaConstraintsMap()
: false, : false,
+34
View File
@@ -5,6 +5,7 @@ import '../../proto/livekit_models.pb.dart' as lk_models;
import '../../types/other.dart'; import '../../types/other.dart';
import '../options.dart'; import '../options.dart';
import '../track.dart'; import '../track.dart';
import 'audio.dart';
import 'local.dart'; import 'local.dart';
/// A video track from the local device. Use static methods in this class to create /// A video track from the local device. Use static methods in this class to create
@@ -63,6 +64,39 @@ class LocalVideoTrack extends LocalTrack with VideoTrack {
options, options,
); );
} }
/// Creates a LocalTracks(audio/video) from the display.
///
/// The current API is mainly used to capture audio when chrome captures tab,
/// but in the future it can also be used for flutter native to open audio
/// capture device when capturing screen
static Future<List<LocalTrack>> createScreenShareTracksWithAudio([
ScreenShareCaptureOptions? options,
]) async {
options ??= const ScreenShareCaptureOptions(captureScreenAudio: true);
final stream = await LocalTrack.createStream(options);
List<LocalTrack> tracks = [
LocalVideoTrack._(
Track.screenShareName,
TrackSource.screenShareVideo,
stream,
stream.getVideoTracks().first,
options,
)
];
if (stream.getAudioTracks().isNotEmpty) {
tracks.add(LocalAudioTrack(
Track.screenShareName,
TrackSource.screenShareAudio,
stream,
stream.getAudioTracks().first,
const AudioCaptureOptions()));
}
return tracks;
}
} }
// //
+4
View File
@@ -82,8 +82,11 @@ class ScreenShareCaptureOptions extends VideoCaptureOptions {
/// See instructions on how to setup your Broadcast Extension here: /// See instructions on how to setup your Broadcast Extension here:
/// https://github.com/flutter-webrtc/flutter-webrtc/wiki/iOS-Screen-Sharing#broadcast-extension-quick-setup /// https://github.com/flutter-webrtc/flutter-webrtc/wiki/iOS-Screen-Sharing#broadcast-extension-quick-setup
final bool useiOSBroadcastExtension; final bool useiOSBroadcastExtension;
final bool captureScreenAudio;
const ScreenShareCaptureOptions({ const ScreenShareCaptureOptions({
this.useiOSBroadcastExtension = false, this.useiOSBroadcastExtension = false,
this.captureScreenAudio = false,
String? sourceId, String? sourceId,
double? maxFrameRate, double? maxFrameRate,
VideoParameters params = VideoParametersPresets.screenShareH720FPS15, VideoParameters params = VideoParametersPresets.screenShareH720FPS15,
@@ -91,6 +94,7 @@ class ScreenShareCaptureOptions extends VideoCaptureOptions {
ScreenShareCaptureOptions.from( ScreenShareCaptureOptions.from(
{this.useiOSBroadcastExtension = false, {this.useiOSBroadcastExtension = false,
this.captureScreenAudio = false,
required VideoCaptureOptions captureOptions}) required VideoCaptureOptions captureOptions})
: super(params: captureOptions.params); : super(params: captureOptions.params);