ブラキオカップ

生刊予言者アルバム

https://github.com/scla-sagauniv/last-tamushun-app

AWS

Python

Docker

Flutter

Dart

ARを使用した写真と動画を紐づけて登録できるアルバムアプリ

shunsuke-tamura

なぎ

s.maru1111

cz0829

推しアイデア

登録した写真をARで認識し,紐づいた動画を重ねて再生することで,思い出をより鮮明に思い起こすことができる

作った背景

アルバムとか見ながら,「この時あんなことあったな」ってなるのを,動画として紐づけて保存できたら便利なのでは

推し技術

・写真とったら撮影時の5秒前が動画として保存される ・ギャラリーのスクロールの慣性 ↑ 意外と実装が大変

プロジェクト詳細

こだわりポイント

フロントエンド

慣性の完成

⬇️こんな感じ

void panInertia(double translationXIncrement) { // 動作が安定せず,回転量が大きい場合は処理を終了 if (translationXIncrement.abs() > 0.3) { return; } // 減速率を回転量の変化量の変化量の逆数に設定 double decelerationRatio = 0.001; double lastIncrementValue = translationXIncrement; final isMinus = translationXIncrement < 0; // 0.1秒ごとに回転させて,回転量を減速率に応じて変更 int cout = 0; Timer.periodic(const Duration(milliseconds: 50), (timer) { // 回転量が小さくなったら終了 if (isMinus) { if (lastIncrementValue > -0.01) { timer.cancel(); } } else { if (lastIncrementValue < 0.01) { timer.cancel(); } } // 中心のアンカーノードを回転 final oldCenterAnchorAngleX = centerAnchorNode.eulerAngles.x; centerAnchorNode.eulerAngles = vector.Vector3(oldCenterAnchorAngleX + lastIncrementValue, 0, 0); // 画像ノードを回転 for (final (idx, pictureNode) in pictureNodes.indexed) { final oldPictureNode = pictureNode.eulerAngles; final newNodeAngleX = centerAnchorNode.eulerAngles.x - idx * (pi / (widget.videoPictures.length / 2)); pictureNode.position = vector.Vector3( centerAnchorNode.position.x - r / 2 * sin(newNodeAngleX), centerAnchorNode.position.y, centerAnchorNode.position.z - r / 2 * cos(newNodeAngleX), ); pictureNode.transform.rotateY(newNodeAngleX - oldPictureNode.x - pi); } // 回転量を減速 if (isMinus) { lastIncrementValue += decelerationRatio; } else { lastIncrementValue -= decelerationRatio; } // decelerationRatio = lastIncrementValue.abs() * 0.2; // 減速率を減少 decelerationRatio *= (1 - cout * cout * 0.001); decelerationRatio = max(decelerationRatio, 0.005); cout++; }); }

写真と動画同時に撮るやつ 要件 ・ 写真を撮影する5秒前の様子を長押しすると見れる ・ ライブラリから写真と動画を選択できる

使ったライブラリ ・ カメラから撮影:camera ・ ライブラリから選択:image_picker ・ 5秒前の動画取得:ffmpeg_kit_flutter

難しかったこと ・ ライブラリから選択の制御 写真・動画一枚づつ取得する非同期処理と、バックグラウンドで動いてるカメラ処理の非同期的な制御がむずかった

・ 5秒前の動画の取得 ffmpeg_kit_flutterは、コマンドベースで動画編集するので、そのコマンドの調節がむずかった

Future<void> trimLastFiveSeconds(String moviePath) async { String time = "5"; // 5秒前の開始時間を計算 String startTime = await calculateStartTime(moviePath); // FFmpegKitを使用して動画をトリミング String command = "-y -i $moviePath -ss $startTime -t $time -c copy $outputPath"; await FFmpegKit.execute(command).then((session) async { final returnCode = await session.getReturnCode(); if (returnCode!.isValueSuccess()) { print("Video trimmed successfully"); } else { print("Failed to trim video"); } }); }

・ 迫り来るスパゲッティコードの恐怖 flutter初めてすぎて気にする余裕ない、バグ修正きつい。

バックエンド

後進育成を意識してシンプルな設計と実装を心がけました おべんきょうになったね

構成図

image

進捗ちらり

https://www.youtube.com/playlist?list=PLiOXM0FsTXiq7XQyU_0zwY4euiVo1JhP7

リポジトリ

フロントエンド

https://github.com/scla-sagauniv/last-tamushun-app

バックエンド

https://github.com/scla-sagauniv/last-tamushun-be

shunsuke-tamura

@shuntamu