voxa_deepar 0.1.2 copy "voxa_deepar: ^0.1.2" to clipboard
voxa_deepar: ^0.1.2 copied to clipboard

PlatformAndroid

DeepAR camera effects for VoxaRTC. Runs on the capture path, before the encoder, so the room sees the effect rather than the streamer previewing it.

example/lib/main.dart

// Camera effects on a live VoxaRTC engine.
//
// The effect runs on the capture path, before the encoder, so it is in the
// published stream — everyone in the room sees it, not just you.
//
// Two things this file cannot supply, because they are yours:
//   * a DeepAR licence key, bound to this app's application id
//   * a .deepar effect file in assets/
//
// See README.md.
import 'package:flutter/material.dart';
import 'package:voxa_deepar/voxa_deepar.dart';
import 'package:voxa_rtc_engine/voxa_rtc_engine.dart';

/// Your VoxaRTC app id.
const appId = 'YOUR_APP_ID';

/// Your DeepAR licence key. Keys are per-platform and bound to the
/// application id — DeepAR fails *silently* on a mismatch, so if effects do
/// nothing and nothing is logged, check this first.
const deepArKey = 'YOUR_DEEPAR_KEY';

/// An effect you dropped into assets/.
const effectAsset = 'assets/my_effect.deepar';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MaterialApp(home: EffectsDemo()));
}

class EffectsDemo extends StatefulWidget {
  const EffectsDemo({super.key});

  @override
  State<EffectsDemo> createState() => _EffectsDemoState();
}

class _EffectsDemoState extends State<EffectsDemo> {
  // Lazy initialisers, not assignments in _start(). build() runs the moment
  // the widget mounts, well before the engine has finished initialising, and
  // the button below reads _effects.isSupported — so assigning it after an
  // await meant the first frames rendered a LateInitializationError. Both
  // constructors are synchronous and cheap, so first access is safe.
  late final RtcEngine _engine = createAgoraRtcEngine();
  late final VoxaDeepAr _effects = VoxaDeepAr(_engine);
  VideoViewController? _preview;
  bool _on = false;
  String _status = 'starting';

  @override
  void initState() {
    super.initState();
    _start();
  }

  Future<void> _start() async {
    await _engine.initialize(const RtcEngineContext(appId: appId));
    await _engine.enableVideo();
    await _engine.startPreview();

    await _effects.setLicenseKey(deepArKey);

    setState(() {
      _preview = VideoViewController(
          rtcEngine: _engine, canvas: const VideoCanvas(uid: 0));
      _status = _effects.isSupported
          ? 'camera on — tap to apply the effect'
          : 'effects are not available on this platform';
    });
  }

  Future<void> _toggle() async {
    if (_on) {
      await _effects.clear();
      setState(() {
        _on = false;
        _status = 'effect off — raw camera';
      });
      return;
    }

    // DeepAR reads effects from disk, so the bundled asset is copied out of
    // the bundle first. Null means it is not in this build.
    final path = await VoxaDeepAr.stageAsset(effectAsset);
    if (path == null) {
      setState(() => _status = 'no effect found at $effectAsset');
      return;
    }

    // setEffect enables on the first call, so this is the only step between
    // a raw camera and a running effect.
    final ok = await _effects.setEffect(path);
    setState(() {
      _on = ok;
      _status = ok ? 'effect on — the room sees this too' : 'could not apply';
    });
  }

  @override
  void dispose() {
    // The native filter outlives this engine, so an effect left enabled would
    // still be attached the next time a camera starts.
    _effects.clear();
    _engine.release();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final preview = _preview;
    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(children: [
        if (preview != null)
          Positioned.fill(child: AgoraVideoView(controller: preview)),
        Positioned(
          left: 16,
          right: 16,
          bottom: 48,
          child: Column(mainAxisSize: MainAxisSize.min, children: [
            Container(
              padding: const EdgeInsets.all(10),
              color: Colors.black54,
              child: Text(_status,
                  style: const TextStyle(color: Colors.white, fontSize: 13)),
            ),
            const SizedBox(height: 12),
            ElevatedButton(
              // Gate on isSupported rather than assuming: a button that always
              // fails is worse than no button.
              onPressed:
                  preview == null || !_effects.isSupported ? null : _toggle,
              child: Text(_on ? 'Turn effect off' : 'Turn effect on'),
            ),
          ]),
        ),
      ]),
    );
  }
}
0
likes
160
points
247
downloads

Documentation

API reference

Publisher

verified publishervoxartc.com

Weekly Downloads

DeepAR camera effects for VoxaRTC. Runs on the capture path, before the encoder, so the room sees the effect rather than the streamer previewing it.

Homepage

License

MIT (license)

Dependencies

flutter, voxa_rtc_engine

More

Packages that depend on voxa_deepar

Packages that implement voxa_deepar