# Project export: 3dReal

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2024
- Tagline: Your memories, but realer
- Devpost: https://devpost.com/software/3dreal
- GitHub: https://github.com/alexkranias/3dReal
- Video: https://www.youtube.com/embed/04GmwLq1Cns?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Result: winner (Entertainment Grand Prize (4x 32in Curved Gaming Monitors))
- Team: 1 GitHub contributor(s) — Alex Kranias (7 commits)

## Devpost submission (written by the team)

### Inspiration

Metaverse, vision pro, spatial video. It’s no doubt that 3D content is the future. But how can I enjoy or make 3d content without spending over 3K? Or strapping massive goggles to my head? Let's be real, wearing a 3d vision pro while recording your child's birthday party is pretty dystopian. And spatial video only gets you so far in terms of being able to interact, it's more like a 2.5D video with only a little bit of depth. How can we relive memories in 3d without having to buy new hardware? Without the friction? Meet 3dReal, where your best memories got realer. It's a new feature we imagine being integrated in BeReal, the hottest new social media app that prompts users to take an unfiltered snapshot of their day through a random notification. When that notification goes off, you and your friends capture a quick snap of where you are! The difference with our feature is based on this idea where if you have multiple images of the same area ie. you and your friends are taking BeReals at the same time, we can use AI to generate a 3d scene. So if the app detects that you are in close proximity to your friends through bluetooth, then you’ll be given the option to create a 3dReal.

### What it does

With just a few images, the AI powered Neural Radiance Fields (NeRF) technology produces an AI reconstruction of your scene, letting you keep your memories in 3d. NeRF is great in that it only needs a few input images from multiple angles, taken at nearly the same time, all which is the core mechanism behind BeReal anyways, making it a perfect application of NeRF. So what can you do with a 3dReal? View in VR, and be able to interact with the 3d mesh of your memory. You can orbit, pan, and modify how you see this moment captures in the 3dReal Since the 3d mesh allows you to effectively view it however you like, you can do really cool video effects like flying through people or orbiting people without an elaborate robot rig. TURN YOUR MEMORIES INTO THE PHYSICAL WORLD - one great application is connecting people through food. When looking through our own BeReals, we found that a majority of group BeReals were when getting food. With 3dReal, you can savor the moment by reconstructing your friends + food, AND you can 3D print the mesh, getting a snippet of that moment forever. How it works Each of the phones using the app has a countdown then takes a short 2-second "video" (think of this as a live photo) which is sent to our Google Firebase database. We group the videos in Firebase by time captured, clustering them into a single shared "camera event" as a directory with all phone footage captured at that moment. While one camera would not be enough in most cases, by using the network of phones to take the picture simultaneously we have enough data to substantially recreate the scene in 3D. Our local machine polls Firebase for new data. We retrieve it, extract a variety of frames and camera angles from all the devices that just took their picture together, use COLMAP to reconstruct the orientations and positions of the cameras for all frames taken, and then render the scene as a NeRF via NVIDIA's instant-ngp repo. From there, we can export, modify, and view our render for applications such as VR viewing, interactive camera angles for creating videos, and 3D printing.

### Challenges we ran into

We lost our iOS developer team member right before the hackathon (he's still goated just unfortunate with school work) and our team was definitely not as strong as him in that area. Some compromises on functionality were made for the MVP, and thus we focused core features like getting images from multiple phones to export the cool 3dReal. There were some challenges with splicing the videos for processing into the NeRF model as well.

### Accomplishments we're proud of

Working final product and getting it done in time - very little sleep this weekend!

### What we learned

A LOT of things out of all our comfort zones - Sunny doing iOS development and Phoebe doing not hardware was very left field, so lots of learning was done this weekend. Alex learned lots about NeRF models.

### What's next

We would love to refine the user experience and also improve our implementation of NeRF - instead of generating a static mesh, our team thinks with a bit more time we could generate a mesh video which means people could literally relive their memories - be able to pan, zoom, and orbit around in them similar to how one views the mesh. BeReal pls hire 👉👈

## README (from the GitHub repository)

# 3dReal
Most recent swift: https://github.com/ZichenYuan/TreeHacks24


## Detected evidence (automated analysis)

Indexed codebase: 515 recognized source files, 8403 KB.
- C (language) — detected in the code
- C++ (language) — detected in the code
- Python (language) — detected in the code
- Swift (language) — detected in the code
- Firebase (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 1040)

```
.gitignore
ios_app/3d-bereal.xcodeproj/project.pbxproj
ios_app/3d-bereal.xcodeproj/project.xcworkspace/contents.xcworkspacedata
ios_app/3d-bereal.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
ios_app/3d-bereal.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
ios_app/3d-bereal.xcodeproj/project.xcworkspace/xcuserdata/zichenyuan.xcuserdatad/WorkspaceSettings.xcsettings
ios_app/3d-bereal.xcodeproj/xcuserdata/zichenyuan.xcuserdatad/xcschemes/xcschememanagement.plist
ios_app/3d-bereal.xcworkspace/contents.xcworkspacedata
ios_app/3d-bereal.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
ios_app/3d-bereal/AppDelegate.swift
ios_app/3d-bereal/Assets.xcassets/AccentColor.colorset/Contents.json
ios_app/3d-bereal/Assets.xcassets/AppIcon.appiconset/Contents.json
ios_app/3d-bereal/Assets.xcassets/Contents.json
ios_app/3d-bereal/Base.lproj/LaunchScreen.storyboard
ios_app/3d-bereal/Base.lproj/Main.storyboard
ios_app/3d-bereal/GoogleService-Info.plist
ios_app/3d-bereal/Info.plist
ios_app/3d-bereal/SceneDelegate.swift
ios_app/3d-bereal/ViewController.swift
ios_app/3d-berealTests/_d_berealTests.swift
ios_app/3d-berealUITests/_d_berealUITests.swift
ios_app/3d-berealUITests/_d_berealUITestsLaunchTests.swift
ios_app/Podfile
ios_app/Podfile.lock
ios_app/Pods/BoringSSL-GRPC/err_data.c
ios_app/Pods/BoringSSL-GRPC/err_data.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/LICENSE
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_bitstr.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_bitstr.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_bool.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_bool.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_d2i_fp.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_d2i_fp.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_dup.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_dup.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_enum.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_enum.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_gentm.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_gentm.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_i2d_fp.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_i2d_fp.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_int.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_int.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_mbstr.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_mbstr.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_object.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_object.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_octet.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_octet.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_print.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_print.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_strex.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_strex.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_strnid.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_strnid.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_time.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_time.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_type.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_type.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_utctm.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_utctm.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_utf8.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/a_utf8.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/asn_pack.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/asn_pack.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/asn1_lib.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/asn1_lib.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/asn1_par.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/asn1_par.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/charmap.h
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/charmap.h.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/f_int.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/f_int.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/f_string.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/f_string.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/internal.h
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/internal.h.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_dec.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_dec.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_enc.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_enc.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_fre.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_fre.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_new.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_new.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_typ.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_typ.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_utl.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/tasn_utl.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/time_support.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/asn1/time_support.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/base64/base64.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/base64/base64.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/bio_mem.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/bio_mem.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/bio.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/bio.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/connect.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/connect.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/fd.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/fd.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/file.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/file.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/hexdump.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/hexdump.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/internal.h
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/internal.h.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/pair.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/pair.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/printf.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/printf.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/socket_helper.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/socket_helper.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/socket.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bio/socket.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/blake2/blake2.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/blake2/blake2.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bn_extra/bn_asn1.c
ios_app/Pods/BoringSSL-GRPC/src/crypto/bn_extra/bn_asn1.c.grpc_back
ios_app/Pods/BoringSSL-GRPC/src/crypto/bn_extra/convert.c
[920 more files omitted for size]
```

### Dependencies

- nerf/requirements.txt: commentjson, imageio, numpy, opencv-python-headless, pybind11, pyquaternion, scipy, tqdm

### Recent commits (newest first)

- Update dreal-f452e-firebase-adminsdk-fjhqq-685204e048.json
- Update README.md
- Update README.md
- Add files via upload
- ios app push
- second
- commit
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### nerf/requirements.txt

```
commentjson
imageio
numpy
opencv-python-headless
pybind11
pyquaternion
scipy
tqdm

```

### nerf/server_to_nerf.py

```python
import firebase_admin
from firebase_admin import credentials
from firebase_admin import storage
from moviepy.editor import VideoFileClip, concatenate_videoclips
import subprocess
import os
import ffmpeg
import time

def concatenate_videos(input_dir, output_file):
    input_files = [f for f in os.listdir(input_dir) if f.endswith('.mov')]
    input_files.sort()

    input_streams = []
    for file in input_files:
        input_streams.append(ffmpeg.input(os.path.join(input_dir, file)))

    # Concatenate the input streams
    ffmpeg.concat(*input_streams, v=1).output(output_file).run()

def loop(blobs):

    # Date Format
    #2024 02 17 14 06 53
    #YYYY MM DD HH MM SS

    # Iterate over the blobs and print their names
    most_recent_dir = 0
    blobs = [blob for blob in blobs if len(blob.name) == 62]
    for blob in blobs:
        name_to_int = int(blob.name[7:21])
        most_recent_dir = max(most_recent_dir, name_to_int)

    most_recent_dir_str = str(most_recent_dir)

    print("\nMost recent directory:", most_recent_dir_str)

    # Download all videos from the most recent directory
    video_dir = os.path.join('data', 'nerf', most_recent_dir_str)
    os.makedirs(video_dir, exist_ok=True)

    for blob in blobs:
        if most_recent_dir_str in blob.name:
            blob.download_to_filename(os.path.join(video_dir, blob.name.split('/')[-1]))

    print(video_dir)

    # List all `.mov` files in the directory
    mov_files = [f for f in os.listdir(video_dir) if (f.endswith('.mov') or f.endswith('.MOV'))]

    # Create a list of VideoFileClip objects from the `.mov` files
    video_clips = [VideoFileClip(os.path.join(video_dir, f)) for f in mov_files]

    video_clips = [clip.rotate(90) for clip in video_clips]

    # Get the first clip's aspect ratio
    aspect_ratio = video_clips[0].size
    print("ASPECT RATIO: ", aspect_ratio)

    # Concatenate video clips
    final_clip = concatenate_videoclips(video_clips, method="compose")

    # Save the final concatenated video with the same resolution as the input clips
    final_clip.write_videofile(os.path.join(video_dir, 'render_this_video.mp4'), codec="libx264")

    # Close the video clips
    for clip in video_clips:
        clip.close()

    print("\nVideos stitched together and saved as 'render_this_video.mp4'")

    # Change the current working directory to data/nerf/most_recent_dir
    os.chdir(video_dir)

    file_name = "render_this_video.mp4"

    # Construct the command
    command = f'C:/Users/alexa/AppData/Local/Programs/Python/Python310/python.exe ..\..\..\scripts\colmap2nerf.py --video_in {file_name} --video_fps 10 --run_colmap --aabb_scale 16 --overwrite'
    subprocess.run(command, shell=True)

    os.chdir(original_dir)

    command = f'.\instant-ngp.exe .\{video_dir}'
    subprocess.run(command, shell=True)


# Initialize Firebase Admin SDK
cred = credentials.Certificate("dreal-f452e-firebase-adminsdk-fjhqq-685204e048.json")
firebase_admin.initialize_app(cred)

# Get a reference to the Firebase Storage service
storage_client = storage

original_dir = os.getcwd()

# List all objects in the videos folder
blobs = storage_client.bucket('dreal-f452e.appspot.com').list_blobs(prefix='videos/')
blobs = [blob for blob in blobs]

while True:
    # Check if there is a new directory every 10 minutes
    curr_blobs = storage_client.bucket('dreal-f452e.appspot.com').list_blobs(prefix='videos/')
    curr_blobs = [blob for blob in curr_blobs]
    print("check", len(curr_blobs), len(blobs))
    if len(curr_blobs) > len(blobs):
        loop(storage_client.bucket('dreal-f452e.appspot.com').list_blobs(prefix='videos/'))

    # Sleep for 10 seconds before checking again
    print("wait")
    blobs = storage_client.bucket('dreal-f452e.appspot.com').list_blobs(prefix='videos/')
    blobs = [blob for blob in blobs]
    time.sleep(5)
```

### ios_app/3d-berealUITests/_d_berealUITestsLaunchTests.swift

```swift
//
//  _d_berealUITestsLaunchTests.swift
//  3d-berealUITests
//
//  Created by Zichen Yuan on 2/17/24.
//

import XCTest

final class _d_berealUITestsLaunchTests: XCTestCase {

    override class var runsForEachTargetApplicationUIConfiguration: Bool {
        true
    }

    override func setUpWithError() throws {
        continueAfterFailure = false
    }

    func testLaunch() throws {
        let app = XCUIApplication()
        app.launch()

        // Insert steps here to perform after app launch but before taking a screenshot,
        // such as logging into a test account or navigating somewhere in the app

        let attachment = XCTAttachment(screenshot: app.screenshot())
        attachment.name = "Launch Screen"
        attachment.lifetime = .keepAlways
        add(attachment)
    }
}

```

### ios_app/3d-berealTests/_d_berealTests.swift

```swift
//
//  _d_berealTests.swift
//  3d-berealTests
//
//  Created by Zichen Yuan on 2/17/24.
//

import XCTest
@testable import _d_bereal

final class _d_berealTests: XCTestCase {

    override func setUpWithError() throws {
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDownWithError() throws {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }

    func testExample() throws {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
        // Any test you write for XCTest can be annotated as throws and async.
        // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
        // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
    }

    func testPerformanceExample() throws {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
        }
    }

}

```

### ios_app/3d-berealUITests/_d_berealUITests.swift

```swift
//
//  _d_berealUITests.swift
//  3d-berealUITests
//
//  Created by Zichen Yuan on 2/17/24.
//

import XCTest

final class _d_berealUITests: XCTestCase {

    override func setUpWithError() throws {
        // Put setup code here. This method is called before the invocation of each test method in the class.

        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = false

        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
    }

    override func tearDownWithError() throws {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }

    func testExample() throws {
        // UI tests must launch the application that they test.
        let app = XCUIApplication()
        app.launch()

        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }

    func testLaunchPerformance() throws {
        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
            // This measures how long it takes to launch your application.
            measure(metrics: [XCTApplicationLaunchMetric()]) {
                XCUIApplication().launch()
            }
        }
    }
}

```

### ios_app/3d-bereal/AppDelegate.swift

```swift
//
//  AppDelegate.swift
//  3d-bereal
//
//  Created by Zichen Yuan on 2/17/24.
//

import UIKit
import FirebaseCore

@main
class AppDelegate: UIResponder, UIApplicationDelegate {



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        FirebaseApp.configure()
        return true
    }

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }


}


```

### ios_app/3d-bereal/SceneDelegate.swift

```swift
//
//  SceneDelegate.swift
//  3d-bereal
//
//  Created by Zichen Yuan on 2/17/24.
//

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else { return }
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        // Called as the scene is being released by the system.
        // This occurs shortly after the scene enters the background, or when its session is discarded.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    func sceneWillResignActive(_ scene: UIScene) {
        // Called when the scene will move from an active state to an inactive state.
        // This may occur due to temporary interruptions (ex. an incoming phone call).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.
    }


}


```

### ios_app/3d-bereal/ViewController.swift

```swift
//
//  ViewController.swift
//  3d-bereal
//
//  Created by Zichen Yuan on 2/17/24.
//

import UIKit
import AVFoundation
import FirebaseStorage
import FirebaseFirestore

class ViewController: UIViewController, AVCaptureFileOutputRecordingDelegate {
    var captureSession: AVCaptureSession!
    var videoOutput: AVCaptureMovieFileOutput!
    var previewLayer: AVCaptureVideoPreviewLayer!
    var recordingStartTime: Date?
    
    @IBOutlet weak var but: UIButton!
    
    @IBOutlet weak var preview: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupCameraSession()
    }
    func setupCameraSession() {
        captureSession = AVCaptureSession()
        captureSession.beginConfiguration()
        
        // Assuming you're using the rear camera
        guard let videoDevice = AVCaptureDevice.default(for: .video),
              let videoInput = try? AVCaptureDeviceInput(device: videoDevice),
              captureSession.canAddInput(videoInput) else { return }
        
        captureSession.addInput(videoInput)
        
        videoOutput = AVCaptureMovieFileOutput()
        if captureSession.canAddOutput(videoOutput) {
            captureSession.addOutput(videoOutput)
        }
        
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer.frame = preview.bounds // Use the bounds of the container view
        previewLayer.videoGravity = .resizeAspectFill
        
        // Add the previewLayer as a sublayer of the container view's layer
        preview.layer.addSublayer(previewLayer)
        
        // Make sure the previewLayer resizes with its superlayer
        previewLayer.frame = preview.layer.bounds
        preview.layer.masksToBounds = true
        
        captureSession.commitConfiguration()
        captureSession.startRunning()
    }


//    func setupCameraSession() {
//        captureSession = AVCaptureSession()
//        captureSession.beginConfiguration()
//
//        // Assuming you're using the rear camera
//        guard let videoDevice = AVCaptureDevice.default(for: .video),
//              let videoInput = try? AVCaptureDeviceInput(device: videoDevice),
//              captureSession.canAddInput(videoInput) else { return }
//
//        captureSession.addInput(videoInput)
//
//        videoOutput = AVCaptureMovieFileOutput()
//        if captureSession.canAddOutput(videoOutput) {
//            captureSession.addOutput(videoOutput)
//        }
//
//        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
//        previewLayer.frame = view.bounds // Adjust as needed
//        previewLayer.videoGravity = .resizeAspectFill
//        view.layer.addSublayer(previewLayer)
//
//        captureSession.commitConfiguration()
//        captureSession.startRunning()
//    }
    
    @IBAction func recordButtonTapped(_ sender: UIButton) {
        recordingStartTime = Date() // Capture the current time as the start time
        let outputPath = NSTemporaryDirectory() + "output.mov"
        let outputFileURL = URL(fileURLWithPath: outputPath)
        
        videoOutput.startRecording(to: outputFileURL, recordingDelegate: self)
        
        // Stop recording after 2 seconds
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            self.videoOutput.stopRecording()
        }
    }
    
    // AVCaptureFileOutputRecordingDelegate methods
    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {
        print("Recording started")
    }
    
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
        print("Recording finished")
        // Handle the recorded video (save or preview it) here
        
   
        // save the video to the photo library
        UISaveVideoAtPathToSavedPhotosAlbum(outputFileURL.path, self, #selector(video(_:didFinishSavingWithError:contextInfo:)), nil)
        
        // save to firebase
        uploadVideoToFirebaseStorage(videoURL:outputFileURL)
        
    }
    
    
    // This is the selector method called after the video has been saved
    @objc func video(_ videoPath: String, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        if let error = error {
            print("Error saving video: \(error.localizedDescription)")
        } else {
            print("Video saved successfully.")
        }
    }
    
    
    //to firebase
    func uploadVideoToFirebaseStorage(videoURL: URL) {
        guard let startTime = recordingStartTime else {
            print("Recording start time is nil")
            return
        }
        
        // Format the date to a string
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyyMMddHHmmss"
        let dateString = dateFormatter.string(from: startTime)
        let baseString = String(dateString.dropLast())
        let flooredDateString = baseString + "0"
        
        // Use the formatted date as part of the file path
        let storageRef = Storage.storage().reference()
        let videoPath = "videos/\(flooredDateString)/\(UUID().uuidString).mov"
        let videosRef = storageRef.child(videoPath)
        
        // Start the upload process
        videosRef.putFile(from: videoURL, metadata: nil) { metadata, error in
            guard let metadata = metadata else {
                print("Error uploading video: \(error?.localizedDescription ?? "Unknown error")")
                return
            }
            print("Video uploaded successfully. Metadata: \(metadata)")
            
            // Optionally, get the download URL
            videosRef.downloadURL { url, error in
                guard let downloadURL = url else {
                    print("Error getting download URL: \(error?.localizedDescription ?? "Unknown error")")
                    return
                
[truncated — 1924 more characters]
```

### ios_app/Pods/BoringSSL-GRPC/err_data.c

```c
/* Copyright (c) 2015, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

 /* This file was generated by err_data_generate.go. */

#include <openssl_grpc/base.h>
#include <openssl_grpc/err.h>
#include <openssl_grpc/type_check.h>


OPENSSL_STATIC_ASSERT(ERR_LIB_NONE == 1, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_SYS == 2, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_BN == 3, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_RSA == 4, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_DH == 5, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_EVP == 6, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_BUF == 7, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_OBJ == 8, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_PEM == 9, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_DSA == 10, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_X509 == 11, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_ASN1 == 12, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_CONF == 13, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_CRYPTO == 14, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_EC == 15, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_SSL == 16, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_BIO == 17, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_PKCS7 == 18, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_PKCS8 == 19, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_X509V3 == 20, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_RAND == 21, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_ENGINE == 22, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_OCSP == 23, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_UI == 24, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_COMP == 25, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_ECDSA == 26, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_ECDH == 27, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_HMAC == 28, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_DIGEST == 29, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_CIPHER == 30, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_HKDF == 31, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_TRUST_TOKEN == 32, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_LIB_USER == 33, "library value changed");
OPENSSL_STATIC_ASSERT(ERR_NUM_LIBS == 34, "number of libraries changed");

const uint32_t kOpenSSLReasonValues[] = {
    0xc320862,
    0xc32887c,
    0xc33088b,
    0xc33889b,
    0xc3408aa,
    0xc3488c3,
    0xc3508cf,
    0xc3588ec,
    0xc36090c,
    0xc36891a,
    0xc37092a,
    0xc378937,
    0xc380947,
    0xc388952,
    0xc390968,
    0xc398977,
    0xc3a098b,
    0xc3a886f,
    0xc3b00f7,
    0xc3b88fe,
    0x1032086f,
    0x103295e5,
    0x103315f1,
    0x1033960a,
    0x1034161d,
    0x10348f4f,
    0x10350c88,
    0x10359630,
    0x1036165a,
    0x1036966d,
    0x1037168c,
    0x103796a5,
    0x103816ba,
    0x103896d8,
    0x103916e7,
    0x10399703,
    0x103a171e,
    0x103a972d,
    0x103b1749,
    0x103b9764,
    0x103c178a,
    0x103c80f7,
    0x103d179b,
    0x103d97af,
    0x103e17ce,
    0x103e97dd,
    0x103f17f4,
    0x103f9807,
    0x10400c4c,
    0x1040981a,
    0x10411838,
    0x1041984b,
    0x10421865,
    0x10429875,
    0x10431889,
    0x1043989f,
    0x104418b7,
    0x104498cc,
    0x104518e0,
    0x104598f2,
    0x10460625,
    0x10468977,
    0x10471907,
    0x1047991e,
    0x10481933,
    0x10489941,
    0x10490e9b,
    0x1049977b,
    0x104a1645,
    0x14320c2f,
    0x14328c3d,
    0x14330c4c,
    0x14338c5e,
    0x143400b9,
    0x143480f7,
    0x18320090,
    0x18328fa5,
    0x183300b9,
    0x18338fbb,
    0x18340fcf,
    0x183480f7,
    0x18350fee,
    0x18359006,
    0x1836101b,
    0x1836902f,
    0x18371067,
    0x1837907d,
    0x18381091,
    0x183890a1,
    0x18390a9d,
    0x183990b1,
    0x183a10d7,
    0x183a90fd,
    0x183b0ca7,
    0x183b914c,
    0x183c115e,
    0x183c9169,
    0x183d1179,
    0x183d918a,
    0x183e119b,
    0x183e91ad,
    0x183f11d6,
    0x183f91ef,
    0x18401207,
    0x184086fd,
    0x18411120,
    0x184190eb,
    0x1842110a,
    0x18428c94,
    0x184310c6,
    0x18439132,
    0x18440fe4,
    0x18449053,
    0x20321241,
    0x2032922e,
    0x2432124d,
    0x243289bd,
    0x2433125f,
    0x2433926c,
    0x24341279,
    0x2434928b,
    0x2435129a,
    0x243592b7,
    0x243612c4,
    0x243692d2,
    0x243712e0,
    0x243792ee,
    0x243812f7,
    0x24389304,
    0x24391317,
    0x28320c7c,
    0x28328ca7,
    0x28330c4c,
    0x28338cba,
    0x28340c88,
    0x283480b9,
    0x283500f7,
    0x28358c94,
    0x2c323286,
    0x2c32932e,
    0x2c333294,
    0x2c33b2a6,
    0x2c3432ba,
    0x2c34b2cc,
    0x2c3532e7,
    0x2c35b2f9,
    0x2c363329,
    0x2c36833a,
    0x2c373336,
    0x2c37b362,
    0x2c383387,
    0x2c38b39e,
    0x2c3933bc,
    0x2c39b3cc,
    0x2c3a33de,
    0x2c3ab3f2,
    0x2c3b3403,
    0x2c3bb422,
    0x2c3c1340,
    0x2c3c9356,
    0x2c3d3436,
    0x2c3d936f,
    0x2c3e3453,
    0x2c3eb461,
    0x2c3f3479,
    0x2c3fb491,
    0x2c4034bb,
    0x2c409241,
    0x2c4134cc,
    0x2c41b4df,
    0x2c421207,
 
[truncated — 29726 more characters]
```

### ios_app/Pods/BoringSSL-GRPC/src/crypto/cpu-ppc64le.c

```c
/* Copyright (c) 2016, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <openssl_grpc/cpu.h>

#if defined(OPENSSL_PPC64LE)

#include <sys/auxv.h>

#include "internal.h"


#if !defined(PPC_FEATURE2_HAS_VCRYPTO)
// PPC_FEATURE2_HAS_VCRYPTO was taken from section 4.1.2.3 of the “OpenPOWER
// ABI for Linux Supplement”.
#define PPC_FEATURE2_HAS_VCRYPTO 0x02000000
#endif

void OPENSSL_cpuid_setup(void) {
  OPENSSL_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
}

int CRYPTO_is_PPC64LE_vcrypto_capable(void) {
  return (OPENSSL_ppc64le_hwcap2 & PPC_FEATURE2_HAS_VCRYPTO) != 0;
}

#endif  // OPENSSL_PPC64LE

```

[480 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]