# Camera and video creation in the Genuin SDK

Record, import, edit, and post video from inside your app with the Genuin camera modules, and control who can create from Brand Control Center.

Members create posts without leaving your app. They record clips with the device camera or import a video from the gallery, trim and decorate it, and post it to a group in your community. Creation ships as a separate module on Android and iOS, so an app that only shows feeds doesn't carry the video toolchain. The Web SDK has no camera; on the web, members create posts in your hosted social experience by uploading a file.

Creation needs a signed-in member. A guest who taps a create action is asked to sign in first. See [Choose how members sign in to the Genuin SDK](https://begenuin.com/developers/developer-resources/sdk/user-authentication-mechanisms-in-genuin-sdk).

## Modules

| Platform | Module | Install | Adds | Requires |
| --- | --- | --- | --- | --- |
| Android | Camera | com.begenuin:camera:2.1.5 (48 MB AAR) | Recording, gallery import, trimmer, editor, post screen, and the background upload service | core, ui |
| iOS | GenuinCamera | pod "GenuinCamera" from https://bitbucket.org/genuindev/genuin_sdk_ios.git, tag 2.1.5 | Recording, gallery import, editor, post screen, and the upload manager | GenuinCore, GenuinUI |
| Web | None | — | The Web SDK renders feeds only. The Create page of your hosted social experience accepts an uploaded MP4 or WebM file. | — |

On Android, Core finds the Camera module at runtime. Without it, a tap on a create action shows your brand's unsupported-feature message as a toast. On iOS, register the module once at launch, after the core SDK:

```swift title="AppDelegate.swift"
import GenuinCore
import GenuinCamera

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  GenuinSDK.shared.initialize(apiKey: "{{API_KEY}}")
  GenuinCamera.shared.initialize()   // registers the camera with Core
  return true
}
```

Without `GenuinCamera.shared.initialize()`, the create actions on iOS return without opening anything.

The camera opens from the create button in feeds and from the reply and video-comment actions. iOS also exposes a direct entry point that signs the member in with your token and presents the camera full screen:

```swift title="Open the camera"
GenuinSDK.shared.initiateCreatePost(
  fromVC: self,
  ssoToken: "{{SSO_TOKEN}}",
  params: ["name": "John Doe", "email": "john.doe@example.com"]   // optional
)
```

## Permissions

The modules don't declare the camera, microphone, or media permissions themselves. Your app declares them, and the SDK checks for the declaration before it opens a camera or gallery screen, then requests access from the member at runtime.

### Android

Add the permissions to your `AndroidManifest.xml`. The Camera module's own manifest declares none of them, and Core declares only `INTERNET`, `ACCESS_NETWORK_STATE`, `VIBRATE`, and `WAKE_LOCK`.

```xml title="AndroidManifest.xml"
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
```

| Permission | Needed for | Without the declaration |
| --- | --- | --- |
| android.permission.CAMERA | Recording clips, profile and community photos, link thumbnails | Create actions show the unsupported-feature toast and log a camera-access-denied event |
| android.permission.RECORD_AUDIO | Audio on recordings, voice comments, on-device transcripts | Same as above; the SDK checks CAMERA and RECORD_AUDIO together before opening the camera |
| android.permission.READ_MEDIA_VIDEO | Gallery import on Android 13 (API 33) and later | The gallery button shows the toast and logs a gallery-access-denied event |
| android.permission.READ_EXTERNAL_STORAGE with android:maxSdkVersion="32" | Gallery import on Android 12 and lower | Same as above on those versions |
| android.permission.WRITE_EXTERNAL_STORAGE | Optional. Saving the finished video to the device from the preview screen on Android 9 and lower | The save button asks for the permission and skips the save if it's denied |

At runtime the SDK requests `CAMERA` and `RECORD_AUDIO` together when the camera opens, and the media permission when the member taps the gallery. A member who denies them sees the SDK's permission screen with a **Settings** button; your app doesn't need its own prompt.

### iOS

Add the usage descriptions to your app's `Info.plist`. Before opening a picker or camera, the SDK checks `Bundle.main` for the key and, when it's missing, shows your brand's unsupported-feature alert instead of crashing. iOS itself terminates an app that accesses the camera or microphone without the key.

```xml title="Info.plist"
<key>NSCameraUsageDescription</key>
<string>Genuin needs permissions to open your camera and microphone. This allows Genuin to record videos that can be shared with other people.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Genuin needs permissions to open your camera and microphone. This allows Genuin to record videos that can be shared with other people.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Genuin needs permissions to access your photo library. This allows Genuin to download videos to your phone and save it to your library.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>The transcript of your recording will be displayed to you in the end for you to overlay it on the audio message.</string>
```

| Info.plist key | Needed for | Requested with |
| --- | --- | --- |
| NSCameraUsageDescription | Recording clips and video comments | AVCaptureDevice.requestAccess(for: .video) when the camera opens |
| NSMicrophoneUsageDescription | Audio on recordings and voice comments | AVCaptureDevice.requestAccess(for: .audio) when the camera opens |
| NSPhotoLibraryUsageDescription | Gallery import, cover images from Photos, saving videos | PHPhotoLibrary.requestAuthorization when the member opens the camera roll; limited access is accepted |
| NSSpeechRecognitionUsageDescription | The transcript shown after an audio recording | SFSpeechRecognizer authorization when the member records audio |

Replace the strings with your own wording; the ones above are Genuin's defaults. `NSContactsUsageDescription`, `NSLocationWhenInUseUsageDescription`, and `NSUserTrackingUsageDescription` belong to other features and are covered in the [iOS SDK guide](https://begenuin.com/developers/developer-resources/sdk/developer/genuin-sdk/native-compatibility/ios/how-to-integrate-and-power-your-brand-community-in-ios-apps).

### Web

No browser permission is involved. Your hosted social experience's **Create** page takes an existing file through a drop zone and never opens the camera or microphone, so there's no `getUserMedia` prompt.

## Recording and upload limits

| Limit | Android | iOS | Web (hosted social experience) |
| --- | --- | --- | --- |
| Post length, maximum | 300 seconds across all clips | 300 seconds across all clips | 300 seconds |
| Post length, minimum | 4 seconds | Not enforced; the record button re-enables 1 second after it starts | 4 seconds |
| Clips per post | No fixed count; the clips add up to the 300-second cap | Same | One file |
| Gallery import | Trimmed to 300 seconds in the import editor | Same | Rejected over 300 seconds |
| Video comment | 120 seconds | 120 seconds | — |
| Audio comment | — | 120 seconds | — |
| Recording speed | 1x, 2x, 4x | 1x, 2x | — |
| Countdown | 3 or 10 seconds, with a stop-recording-after timer | 3 seconds, with a stop-recording-after timer in 0.05-second steps | — |
| Capture | 1280x720 when the camera offers it, otherwise the first 1920-wide size; H.264 video and AAC audio at the device's QUALITY_HIGH bit rate and frame rate | AVCaptureSession preset 1280x720; export preset 1280x720 | — |
| Output | Portrait MP4 merged with FFmpeg to the size that matches the screen ratio: 640x960, 688x1220 (16:9), 720x1354 (17:9), 736x1472 (18:9), 760x1604 (19:9), or 800x1776 (20:9) | Portrait MP4 | Uploaded as-is |
| File size | No client-side cap; the upload reports the size as video_size | No client-side cap | 2 GB, MP4 or WebM, 9:16 aspect ratio |
| Description | 2,000 characters | Not verified | Not verified |

The merge step scales each clip to the output size and pads it rather than cropping, so a landscape import keeps its full frame with bars above and below.

## Editing tools

| Tool | Android | iOS |
| --- | --- | --- |
| Trim, reorder, retake, and delete clips | Trimmer with a frame strip, edit-clips and delete-clip actions on the camera | Gallery video editor and clip editor with an add-clip cell while the total is under 300 seconds |
| Text overlay | Eight fonts, colours, a transparent, white, or black background, and left, centre, or right alignment | Same eight fonts: Inter (two styles), Bebas Neue, Courier Prime, Scope One, Lora, Varela Round, Nunito |
| Stickers | GIPHY picker with Recents, Stickers, Text, and Emoji tabs | Same picker, draggable |
| Question overlay | For Q&A posts: pick, shuffle, add, or edit a question | Question editor and draggable question view |
| Link card | Preview of a shared link on the video | Draggable link view |
| Cover image | Pick a frame as the thumbnail, or change it later | Cover image selection |
| Transcript | On-device speech-to-text shown under audio-only posts | Apple speech recognition shown after an audio recording |
| Post screen | Description with @mentions, cover, add link, Post to group picker, privacy | Same fields |

Background music, transitions, and AI-generated captions aren't in version 2.1.5 of either module. [Edit videos in the Genuin SDK](https://begenuin.com/developers/get-started/brand-control-center/what-are-the-video-editing-tools-in-the-genuin-sdk) describes each tool in detail.

## Who can create

Three levels decide whether a member sees a create button and where the post can go.

**Brand.** Three flags on your brand record gate creation everywhere: `camera_enabled` (default on) shows or hides camera entry points, `post_enabled` (default on) shows or hides the create button in SDK feeds, and `create_post_enabled` (default off) shows the **Create** button on your hosted social experience. The Genuin team sets them; there's no screen for them in Brand Control Center.

**Community.** In Brand Control Center, go to **Manage** > **Communities**, open the community, and under **Who can create Groups** choose **All community members** or **Admins**. The same choice appears when you create a community.

**Group.** Posts always belong to a group. Go to **Manage** > **Groups**, open the group, and set its two access options. The choices depend on the community's privacy:

| Community | Who can see this Group | Who can post in this Group |
| --- | --- | --- |
| Public | Everyone (including people without an account) or Group Members only | All community members or Group Members only |
| Private | All community members or Group Members only | All community members or Invite-only (members you invite or approve) |

The SDK's post screen offers the member only the groups they're allowed to post in.

## Limitations

- **Portrait only**: The camera records and exports portrait video; landscape imports are padded, not rotated.
- **Module size**: The Android Camera module adds about 48 MB before compression because it bundles the FFmpeg toolchain and the on-device speech model.
- **No camera on the web**: The Web SDK can't record or upload. Creation on the web is your hosted social experience's **Create** page, which takes one MP4 or WebM file of 4 to 300 seconds and up to 2 GB.
- **Permissions are yours to declare**: The SDK checks your manifest or `Info.plist` and shows the unsupported-feature message when a declaration is missing; it never adds permissions.
- **Brand flags aren't self-serve**: `camera_enabled`, `post_enabled`, and `create_post_enabled` change through the Genuin team.
- **No music, transitions, or AI captions** in the 2.1.5 camera modules.
- **Signed-in members only**: Guests are asked to sign in before the camera opens.

## See also

- [Integrate the Genuin Android SDK](https://begenuin.com/developers/developer-resources/sdk/how-to-integrate-and-power-your-brand-community-in-android-apps)
- [Integrate the Genuin iOS SDK](https://begenuin.com/developers/developer-resources/sdk/developer/genuin-sdk/native-compatibility/ios/how-to-integrate-and-power-your-brand-community-in-ios-apps)
- [Choose how members sign in to the Genuin SDK](https://begenuin.com/developers/developer-resources/sdk/user-authentication-mechanisms-in-genuin-sdk)
- [How Auto Login works](https://begenuin.com/developers/developer-resources/sdk/genuin-auto-login)
- [Set up push notifications in the Genuin SDK](https://begenuin.com/developers/get-started/developers/genuin-sdk/creation-n-editing-tools/how-do-push-notifications-work-with-the-genuin-sdk)
- [Request camera, microphone, and photo library permissions](https://begenuin.com/developers/developer-resources/sdk/request-camera-microphone-and-photo-library-permissions)
- [Edit videos in the Genuin SDK](https://begenuin.com/developers/get-started/brand-control-center/what-are-the-video-editing-tools-in-the-genuin-sdk)
