> ## Documentation Index
> Fetch the complete documentation index at: https://cloudinary.com/documentation/llms.txt
> Use this file to discover all available pages before exploring further.

# Flutter video player


The Flutter SDK includes a Cloudinary native video player built on top of the [Video Player plugin for Flutter](https://pub.dev/packages/video_player). This makes it easy to use the various Cloudinary video capabilities and deliver your videos using the device's native player. For Android, the player uses [ExoPlayer](https://exoplayer.dev/) and for iOS it uses [AVPlayer](https://developer.apple.com/documentation/avfoundation/avplayer/).

To create a player, use the `CldVideoController` to create a new controller instance and provide either the public ID for the video or the full Cloudinary URL:

```dart
//Public ID
final CldVideoController _controller = CldVideoController(publicId: 'dog');

//URL 
final CldVideoController _controller = CldVideoController.networkUrl(Uri.parse('https://res.cloudinary.com/demo/video/upload/sp_auto/dog.m3u8'));


```
> **NOTE**: If you haven't set your Cloudinary credentials as an environment variable, you need to include the `cloudinary` object alongside the `publicId` parameter. For example:

```dart
Cloudinary cloudinary = CloudinaryObject.fromCloudName(cloudName: '<your_cloud_name>');
final CldVideoController _controller = CldVideoController(cloudinary: cloudinary, publicId: 'dog');
```

Once you have the player controller instance, you can add that to the `VideoPlayer` imported from the Video Player plugin.

Here's a fully working example of a simple view that renders the video player and a play/pause button:

```dart
import 'package:cloudinary_flutter/cloudinary_object.dart';
import 'package:cloudinary_flutter/video/cld_video_controller.dart';
import 'package:cloudinary_url_gen/cloudinary.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';

void main() => runApp(const VideoApp());

/// Stateful widget to fetch and then display video content.
class VideoApp extends StatefulWidget {
  const VideoApp({super.key});

  @override
  _VideoAppState createState() => _VideoAppState();
}

class _VideoAppState extends State<VideoApp> {
  late CldVideoController _controller;
  Cloudinary cloudinary = CloudinaryObject.fromCloudName(cloudName: 'demo');


  @override
  void initState() {
    super.initState();
    
    _controller = CldVideoController(cloudinary: cloudinary, publicId: 'dog')
      ..initialize().then((_) {
        // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
        setState(() {});
      });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Demo',
      home: Scaffold(
        body: Center(
          child: _controller.value.isInitialized
              ? AspectRatio(
                  aspectRatio: _controller.value.aspectRatio,
                  child: VideoPlayer(_controller),
                )
              : Container(),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              _controller.value.isPlaying
                  ? _controller.pause()
                  : _controller.play();
            });
          },
          child: Icon(
            _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}

```

## Transformations

You can include video transformations as part of your `CldVideoController` instance to generate a variation of the original asset. The transformations are defined when initializing the player. For example:

```dart
final CldVideoController _controller = CldVideoController(publicId: 'dog.m3u8', transformation: Transformation().videoEdit(VideoEdit.trim().startOffset("3.0")));
```

> **NOTE**: [Automatic streaming profile selection](adaptive_bitrate_streaming#automatic_streaming_profile_selection) is enabled by default. This currently has a [limited set of transformations](adaptive_bitrate_streaming#combining_transformations_with_automatic_streaming_profile_selection) that you can combine with it, therefore when using any transformations, automatic streaming profile selection will be disabled. 
If you want to include both, check that your transformations are supported and set the streaming profile transformation to `auto` when initializing your player, for example:

  ```dart
final CldVideoController _controller = CldVideoController(publicId: 'dog.m3u8', transformation: Transformation().transcode(Transcode.streamingProfile(StreamingProfile.auto())).videoEdit(VideoEdit.trim().startOffset("3.0")));

  ```