I recently developed a plugin for Xamarin.Foms to trim videos. In this post I would like to give a small demonstration on how to use the same. The plugin is published as a Nuget Package : Xamarin.Forms.VideoTrimmer. It’s source code and a demo lives inside a repository in my Github account. At the moment this package targets Android and iOS only.

API Usage

Task<bool> VideoTrimmerService. Instance. TrimAsync ( int startMS, int lengthMS, string inputPath, string outputPath )

  • startMS : starting point of the Trimmed video in milliseconds.
  • lengthMS : length of the Trimmed video in milliseconds.
  • inputPath : path of the video to be trimmed.
  • outputPath : destination path of the trimmed video.

Note: Trimmed video will be in mp4 and mov formats in Android and iOS respectively. outputPath should take care of this.

Sample Xamarin.Forms app to Trim Video

Video Trimmer Xamarin.Forms App Android & iOS

Let’s get our hands dirty. Let’s develop a small application in which we choose a video from the device, trims it and shares the trimmed version to other apps. To start with, create a blank Xamarin.Forms app targeting Android and iOS.

Adding Necessary Nuget packages

Video Trimming Page

In the Video Trimming page, we will have:

  1. Pick VideoButton tapping which we will select the video to be trimmed.
  2. StatusLabel which displays what is the action to be taken.
  3. Starting Time in SecondsEntry to enter the starting point of trimmed video in seconds.
  4. LengthEntry to enter the required length of the trimmed video.
  5. Trim and Share VideoButton to initiate video trimming and sharing the trimmed video to other apps.

Trimming page XAML

<Grid Padding="20"
        ColumnSpacing="20"
        RowSpacing="20"
        VerticalOptions="Center">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="40"/>
        <RowDefinition Height="40"/>
        <RowDefinition Height="40"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Button Text="Pick Video"
            Clicked="PickVideo_Clicked"
            Grid.ColumnSpan="2"
            BackgroundColor="DeepSkyBlue"
            TextColor="White"/>
    <Label x:Name="Status"
            HorizontalTextAlignment="Center"
            Grid.Row="1"
            Grid.ColumnSpan="2"
            Text="Pick a Video First" />
    <Entry x:Name="StartTime"
            Placeholder="Starting Time in Seconds"
            Grid.Row="2"/>
    <Entry x:Name="Length"
            Placeholder="Length in Seconds"
            Grid.Row="2"
            Grid.Column="1"/>
    <Button Text="Trim and Share Video"
            Clicked="TrimVideo_Clicked"
            Grid.Row="3"
            Grid.ColumnSpan="2"
            BackgroundColor="DeepSkyBlue"
            TextColor="White"/>
    <StackLayout x:Name="TrimmingIndicatorView"
                    BackgroundColor="LightGray"
                    Grid.RowSpan="4"
                    Grid.ColumnSpan="2"
                    IsVisible="False">
        <ActivityIndicator HorizontalOptions="Center"
                            IsRunning="True"
                            VerticalOptions="EndAndExpand"/>
        <Label Text="Trimming Video"
                HorizontalOptions="Center"
                VerticalOptions="StartAndExpand"/>
    </StackLayout>
</Grid>

In the code behind class for the page, let’s create a method which will check for required permissions and then request permissions that are not already granted. We will be using Permissions API from Xamarin.Essentials.

private async Task<bool> CheckAndRequestPermissionAsync<TPermission>(string permissionName) 
where TPermission : Permissions.BasePermission, new()
{
    try
    {
        var status = await Permissions.CheckStatusAsync<TPermission>();
        if (status != PermissionStatus.Granted)
        {
            status = await Permissions.RequestAsync<TPermission>();
            if (status != PermissionStatus.Granted)
            {
                if (status == PermissionStatus.Denied)
                {
                    await DisplayAlert("Permission Required", "Please enable " + permissionName + 
                    " permission to carry on with this operation.", "OK");
                }
            }
        }
        if (status == PermissionStatus.Granted || status == PermissionStatus.Unknown)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    catch (Exception ex)
    {
        return false;
    }
}

Now let’s define PickVideo_Clicked method. We will be using Xam.Plugin.Media to pick video.

async void PickVideo_Clicked(System.Object sender, System.EventArgs e)
{
    await CrossMedia.Current.Initialize();
    if (await CheckAndRequestPermissionAsync<Permissions.StorageRead>("Read Storage")
        && await CheckAndRequestPermissionAsync<Permissions.StorageWrite>("Write Storage")
        && await CheckAndRequestPermissionAsync<Permissions.Photos>("Photos"))
    {
        if (!CrossMedia.Current.IsPickVideoSupported)
        {
            await DisplayAlert("No Gallery Access", ":( No access to gallery available.", "OK");
            return;
        }
        if (isBusy)
            return;
        isBusy = true;
        var file = await CrossMedia.Current.PickVideoAsync();
        if (file == null)
        {
            isBusy = false;
            return;
        }
        Status.Text = "Video Picked. Enter Start time and Length required, and press Trim Button";
        inputFilePath = file.Path;
        isBusy = false;
    }
}

Now let’s define TrimVideo_Clicked method. We will be using Xamarin.Forms.VideoTrimmer to trim the video and Share API from Xamarin.Essentials to share the trimmed video

async void TrimVideo_Clicked(System.Object sender, System.EventArgs e)
{
    int startTime, endTime;

    if (!int.TryParse(StartTime.Text, out startTime))
    {
        await DisplayAlert("", "Start Time is not in proper format", "OK");
        return;
    }
    if (!int.TryParse(Length.Text, out endTime))
    {
        await DisplayAlert("", "Length is not in proper format", "OK");
        return;
    }
    if (string.IsNullOrWhiteSpace(inputFilePath))
    {
        await DisplayAlert("", "Video for trimming is not selected", "OK");
        return;
    }
    string fileName = DateTime.Now.ToString("yyyyMMddhhmmss") 
    + (Device.RuntimePlatform == Device.iOS ? ".mov" : ".mp4");
string outputPath = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, fileName);
    TrimmingIndicatorView.IsVisible = true;
    try
    {
        if (await VideoTrimmerService.Instance.TrimAsync(startTime * 1000, endTime * 1000, inputFilePath, outputPath))
        {
            await DisplayAlert("", "Video Trimmed Successfully", "OK");
            await Share.RequestAsync(new ShareFileRequest
            {
                Title = Title,
                File = new ShareFile(outputPath)
            });
        }
        else
        {
            await DisplayAlert("", "Video Trimming failed", "OK");
        }
    }
    finally
    {
        TrimmingIndicatorView.IsVisible = false;
    }
}

Happy Coding :-)