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

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> {
  late final RtcEngine _engine;
  late final VoxaDeepAr _effects;
  VideoViewController? _preview;
  bool _on = false;
  String _status = 'starting';

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

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

    _effects = VoxaDeepAr(_engine);
    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
0
points
247
downloads

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

unknown (license)

Dependencies

flutter, voxa_rtc_engine

More

Packages that depend on voxa_deepar

Packages that implement voxa_deepar