record method
Future<MiniProgramMicrophoneResult>
record({
- required String miniProgramId,
- required MiniProgramMicrophonePolicy policy,
- int maxDurationSeconds = 60,
- VoidCallback? onStarted,
Implementation
Future<MiniProgramMicrophoneResult> record({
required String miniProgramId,
required MiniProgramMicrophonePolicy policy,
int maxDurationSeconds = 60,
VoidCallback? onStarted,
}) async {
if (_disposed) throw StateError('Microphone manager is disposed.');
if (!policy.enabled) {
throw const MiniProgramMicrophoneException(
errorCode: MiniProgramErrorCodes.microphoneNotAccepted,
message: 'Microphone recording is not accepted by host policy.',
);
}
if (maxDurationSeconds < 1 ||
maxDurationSeconds > 600 ||
policy.maxDurationSeconds < 1 ||
policy.maxDurationSeconds > 600 ||
policy.maxBytes < 1 ||
policy.maxBytes > 100 * 1024 * 1024) {
throw const MiniProgramMicrophoneException(
errorCode: MiniProgramErrorCodes.microphoneInvalidRequest,
message: 'The recording request or accepted limits are invalid.',
);
}
if (_active != null) {
throw const MiniProgramMicrophoneException(
errorCode: MiniProgramErrorCodes.microphoneRequestInProgress,
message: 'A microphone recording is already in progress.',
);
}
final operation = _MicrophoneOperation(
'recording_${DateTime.now().microsecondsSinceEpoch}_${++_sequence}',
miniProgramId,
);
_active = operation;
final duration = math.min(maxDurationSeconds, policy.maxDurationSeconds);
MiniProgramMicrophoneResult? result;
bool registered = false;
Object? callbackError;
try {
result = await provider.record(
MiniProgramMicrophoneRequest(
recordingId: operation.id,
miniProgramId: miniProgramId,
maxDurationSeconds: duration,
maxBytes: policy.maxBytes,
),
onStarted: () {
if (_disposed ||
operation.cancelled ||
!identical(_active, operation) ||
operation.started) {
return;
}
operation.started = true;
try {
onStarted?.call();
} on Object catch (error) {
callbackError = error;
unawaited(cancelFor(miniProgramId));
}
},
);
if (operation.cancelled || _disposed) {
throw const MiniProgramMicrophoneException(
errorCode: MiniProgramErrorCodes.microphoneRecordingCancelled,
message: 'Microphone recording was cancelled.',
);
}
result.validate();
if (result.recordingId != operation.id ||
mediaManager.isRegistered(result.mediaRef)) {
throw const MiniProgramMicrophoneException(
errorCode: MiniProgramErrorCodes.microphoneInvalidResult,
message: 'The host returned an invalid recording reference.',
);
}
// Native encoders may finalize a frame just beyond the timer boundary.
if (result.bytes > policy.maxBytes ||
result.durationMs > duration * 1000 + 1000) {
throw const MiniProgramMicrophoneException(
errorCode: MiniProgramErrorCodes.microphoneLimitExceeded,
message: 'The recording exceeds accepted host limits.',
);
}
mediaManager.register(
miniProgramId: miniProgramId,
mediaRef: result.mediaRef,
);
registered = true;
_owners[result.mediaRef] = miniProgramId;
return result;
} catch (error) {
if (result != null) {
if (registered) {
await releaseRecording(miniProgramId, result);
} else if (!mediaManager.isRegistered(result.mediaRef)) {
await _releaseNative(miniProgramId, result.mediaRef);
}
}
if (callbackError != null) throw callbackError!;
if (error is FormatException || error is MiniProgramMediaException) {
throw const MiniProgramMicrophoneException(
errorCode: MiniProgramErrorCodes.microphoneInvalidResult,
message: 'The host returned invalid recording metadata.',
);
}
rethrow;
} finally {
if (identical(_active, operation)) _active = null;
}
}