> ## Documentation Index
> Fetch the complete documentation index at: https://social-b97141fb-feat-user-history-moderation-detail.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Video Handling

> Upload videos and read transcoding status or resolution URLs with the social.plus SDKs.

Use video handling when your app needs to upload video files for posts, messages, stories, clips, or other media experiences. Video uploads return a video file object with a `fileId`, original URL, and, on platforms that expose it, transcoding status and a map of generated resolution URLs.

The SDK exposes upload progress and video file metadata. Playback UI, caching, retry policy, and adaptive player behavior remain application concerns.

## Platform Surface

| Platform | Upload | Fetch | Status and resolutions | Frame dimensions | Notes |
| - | - | - | - | - | - |
| TypeScript | `FileRepository.uploadVideo(formData, feedType?, onProgress?)` | `FileRepository.getFile(fileId)` | `status` and `videoUrl` on the returned file | `getWidth()`, `getHeight()`, and `getRotation()` on a `'video'` file. Requires `@amityco/ts-sdk` 7.27.0 or later. | `ContentFeedType` includes `story`, `clip`, `chat`, `post`, and `message`. |
| iOS | `AmityFileRepository.uploadVideo(with:progress:)` and `uploadVideo(with:feedType:progress:completion:)` | `getFile(fileId:)`, then `mapToVideoData()` | `AmityVideoData.status`, `videoUrls`, and `getVideo(resolution:)` | No dedicated accessors. Read `attributes["metadata"]["video"]` off `AmityVideoData`. | The async upload method checks for files over 1 GB. The feed-type callback overload checks 4 GB and 2 hours. |
| Android | `AmityCoreClient.newFileRepository().uploadVideo(uri, contentFeedType)` | `getFile(fileId)`, then `asAmityVideo()` | `getStatus()`, `getResolutions()`, and `getVideoUrl(resolution)` | `getWidth()`, `getHeight()`, and `getRotation()` on `AmityVideo`. Requires Android SDK 7.26.0 or later. | `AmityContentFeedType` exposes `STORY`, `CLIP`, `MESSAGE`, and `POST`. |
| Flutter | `AmityCoreClient.newFileRepository().uploadVideo(file, feedtype?)` | Not exposed as a direct public file-repository fetch method in the current SDK | `AmityVideo.getResolutions()` and `getVideoUrl(resolution)` on video objects | `fileProperties.width` and `fileProperties.height` only. Rotation is not exposed. | `AmityContentFeedType` exposes `STORY`, `POST`, `MESSAGE`, and `CLIP`. |

## Parameters

| Parameter | Platforms | Description |
| - | - | - |
| `formData` / `url` / `uri` / `file` | TypeScript, iOS, Android, Flutter | The local video input. TypeScript expects `FormData` with a `files` key; iOS accepts a local `URL`; Android accepts `Uri`; Flutter accepts `File`. |
| `feedType` / `contentFeedType` / `feedtype` | TypeScript, iOS, Android, Flutter | Optional or required video context depending on platform. It tells the backend which content surface the video is for. |
| `fileId` | TypeScript, iOS, Android | ID returned by upload or embedded in content data. Used for direct fetch where available. |
| `resolution` | TypeScript, iOS, Android, Flutter | Requested generated video URL. Exposed values include original, 1080p, 720p, 480p, and 360p where available for that upload. |
| `onProgress` / `progress` | TypeScript, iOS, Android, Flutter | Upload progress callback or stream event. |

## Upload A Video

Upload a video first, then use the returned video object or `fileId` in video-based content APIs.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ContentFeedType, FileRepository } from '@amityco/ts-sdk';

  async function uploadVideo(video: File) {
    const formData = new FormData();
    formData.append('files', video);

    const { data: videos } = await FileRepository.uploadVideo(
      formData,
      ContentFeedType.POST,
      percent => {
        console.log(`Upload progress: ${percent}%`);
      },
    );

    return videos[0].fileId;
  }
  ```

  ```swift iOS theme={null}
  let videoURL = URL(fileURLWithPath: "/tmp/video.mov")

  let uploadedVideo = try await fileRepository.uploadVideo(
      with: videoURL,
      progress: { progress in
          print("Upload progress: \(progress)")
      }
  )

  let videoFileId = uploadedVideo.fileId
  ```

  ```kotlin Android theme={null}
  val videoUri = Uri.parse("file:///tmp/video.mp4")

  AmityCoreClient.newFileRepository()
      .uploadVideo(
          uri = videoUri,
          contentFeedType = AmityContentFeedType.POST
      )
      .doOnNext { result: AmityUploadResult<AmityVideo> ->
          when (result) {
              is AmityUploadResult.PROGRESS -> {
                  val progress = result.getUploadInfo().getProgressPercentage()
              }
              is AmityUploadResult.COMPLETE -> {
                  val uploadedVideo = result.getFile()
                  val videoFileId = uploadedVideo.getFileId()
              }
              is AmityUploadResult.ERROR -> {
                  val error = AmityError.from(result.getError())
              }
              is AmityUploadResult.CANCELLED -> {
                  // Upload was canceled.
              }
          }
      }
      .subscribe()
  ```

  ```dart Flutter theme={null}
  import 'dart:io';

  final video = File('/tmp/video.mp4');

  AmityCoreClient.newFileRepository()
      .uploadVideo(video, feedtype: AmityContentFeedType.POST)
      .stream
      .listen((AmityUploadResult<AmityVideo> result) {
    result.when(
      progress: (uploadInfo, cancelToken) {
        final progress = uploadInfo.getProgressPercentage();
      },
      complete: (uploadedVideo) {
        final videoFileId = uploadedVideo.fileId;
        final resolutions = uploadedVideo.getResolutions();
      },
      error: (error) {
        final exception = error;
      },
      cancel: () {
        // Upload was canceled.
      },
    );
  });
  ```
</CodeGroup>

## Read Video Status And URLs

Read video status and resolution URLs when your UI needs to render playback or processing state. The returned video file also carries the frame dimensions, but each platform surfaces them differently — see the **Frame dimensions** column above for the accessor and the minimum SDK version.

Width and height are the **stored** (pre-rotation) values. Apply the rotation to get the displayed orientation: swap width and height when `rotation % 180 != 0`.

<Warning>
  Flutter exposes the stored width and height but **no rotation**. Width and height alone cannot determine the display orientation of a rotated video; use a media player or parser that handles orientation metadata.
</Warning>

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { FileRepository } from '@amityco/ts-sdk';

  async function getVideo(videoFileId: string) {
    // getFile does not narrow its return type, so cast to the video file shape
    // before reading the video-only members.
    const { data } = await FileRepository.getFile(videoFileId);
    const video = data as Amity.File<'video'>;
    const playbackUrl = video.videoUrl?.['720p'] ?? video.fileUrl;

    return {
      playbackUrl,
      status: video.status,
      width: video.getWidth(),
      height: video.getHeight(),
      rotation: video.getRotation(),
    };
  }
  ```

  ```swift iOS theme={null}
  let rawFile = try await fileRepository.getFile(fileId: videoFileId)

  if rawFile.type == .video, let videoData = rawFile.mapToVideoData() {
      let status = videoData.status
      let resolutions = Array(videoData.videoUrls.keys).sorted()
      let playbackURL = videoData.getVideo(resolution: .res_720p)

      // Stored frame dimensions. iOS has no dedicated accessors — read the raw metadata.
      let videoStream = (videoData.attributes["metadata"] as? [String: Any])?["video"] as? [String: Any]
      let width = videoStream?["width"] as? Int
      let height = videoStream?["height"] as? Int
      let rotation = videoStream?["rotation"] as? Int
  }
  ```

  ```kotlin Android theme={null}
  import com.amity.socialcloud.sdk.helper.core.asAmityVideo

  AmityCoreClient.newFileRepository()
      .getFile(videoFileId)
      .doOnSuccess { rawFile: AmityRawFile ->
          val video = rawFile.asAmityVideo()
          val status = video?.getStatus()
          val resolutions = video?.getResolutions().orEmpty()
          val playbackUrl = video?.getVideoUrl(AmityVideoResolution.RES_720)
          val width = video?.getWidth()
          val height = video?.getHeight()
          val rotation = video?.getRotation()
      }
      .subscribe()
  ```

  ```dart Flutter theme={null}
  void inspectVideo(AmityVideo video) {
    final resolutions = video.getResolutions();
    final playbackUrl = video.getVideoUrl(AmityVideoResolution.RES_720);

    // Stored frame dimensions. They live on the file properties, not on AmityVideo,
    // and Flutter does not expose the rotation that goes with them.
    final int? width = video.fileProperties.width;
    final int? height = video.fileProperties.height;
  }
  ```
</CodeGroup>

## Related Topics

<CardGroup cols={3}>
  <Card title="Video Posts" icon="video" href="/social-plus-sdk/social/content-management/posts/creation/video-post">
    Attach uploaded videos to social posts.
  </Card>

  <Card title="File Handling" icon="file" href="./file">
    Upload and inspect generic file attachments.
  </Card>

  <Card title="Clip Posts" icon="clapperboard" href="/social-plus-sdk/social/content-management/posts/creation/clip-post">
    Create short-form clip posts where supported.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.