Skip to content

fix: 커스텀 사운드 키링 영상 생성 실패 버그 수정#61

Merged
giljihun merged 4 commits into
developfrom
bugfix/-키링-만들기---커스텀-사운드-사용-키링영상-미생성-버그
Feb 9, 2026

Hidden character warning

The head ref may contain hidden characters: "bugfix/-\ud0a4\ub9c1-\ub9cc\ub4e4\uae30---\ucee4\uc2a4\ud140-\uc0ac\uc6b4\ub4dc-\uc0ac\uc6a9-\ud0a4\ub9c1\uc601\uc0c1-\ubbf8\uc0dd\uc131-\ubc84\uadf8"
Merged

fix: 커스텀 사운드 키링 영상 생성 실패 버그 수정#61
giljihun merged 4 commits into
developfrom
bugfix/-키링-만들기---커스텀-사운드-사용-키링영상-미생성-버그

Conversation

@giljihun
Copy link
Copy Markdown
Member

@giljihun giljihun commented Feb 9, 2026

🎯 PR 내용

커스텀 사운드를 사용한 키링에서 영상 공유 시, 영상 생성이 실패하는 버그를 수정했씁니다.

일반 사운드(프리셋)를 사용한 키링만 정상 동작했음.
내용이 조금 복잡할 수 있는데, 마지막까지 읽으면 이해가 될 것 같습니다.

원인 분석

1. Firebase Storage URL 파일명 추출 오류

Firebase Storage URL 구조는 이렇습니다.

https://firebasestorage.googleapis.com/v0/b/.../o/Keyrings%2FCustomSounds%2Fuid%2FUUID.m4a?alt=media&token=xxx

기존 코드 (EffectSyncManager.swift):

let pathComponents = downloadURL.path.components(separatedBy: "/")
let fileName = pathComponents.last ?? "custom_sound.m4a"

문제점

  • downloadURL.path는 URL 인코딩된 전체 경로를 반환
  • path.last의 결과: Keyrings%2FCustomSounds%2Fuid%2FUUID.m4a (잘못된 파일명)
  • 실제 필요한 파일명: UUID.m4a

KeyringVideoGenerator도 동일한 문제:

  • file:// 또는 / 시작 경로만 처리하고, https:// Firebase URL은 처리하지 못했음.

2. 새로 생성된 키링의 사운드가 캐시에 없음

키링 생성 플로우는 아래와 같습니다.

녹음 → Firebase 업로드 → Firestore 저장 → CompleteView → 공유 클릭

문제점

  • 1. EffectSyncManager는 보관함에서 키링 조회 시에만 사운드를 다운로드
  • 2. 새로 만든 키링은 CompleteView에서 바로 공유하므로 캐시에 사운드 파일이 없음
  • 3. KeyringVideoGenerator가 캐시에서 파일을 찾지 못해 실패!

3. viewModel.soundId가 업데이트되지 않음

기존 코드

  self.uploadSoundToStorage(soundURL: customSoundURL, uid: uid) { soundURL in
      // soundURL = Firebase Storage URL
      self.createKeyringWithData(uid: uid, imageURL: imageURL, soundId: soundURL)
      // viewModel.soundId는 여전히 "custom_recording"
  }

Firestore에는 Firebase URL이 저장되지만, viewModel.soundId는 "custom_recording" 그대로
CompleteView에서 영상 생성 시 "custom_recording"으로 사운드를 찾으려 함

결론적으로,
아래 플로우대로 수정이 되어야 합니다.

녹음 → Firebase 업로드 → 로컬 파일을 캐시에 복사 (추가) → Firestore 저장 → CompleteView → 공유 클릭

해결!

1. Firebase Storage URL 파일명 추출 로직 수정 (+공용화)

String+Extension.swift

extension String {
	var firebaseStorageFileName: String {
		// /o/ 이후의 경로 추출
		guard let oRange = range(of: "/o/") else {
			return URL(string: self)?.lastPathComponent ?? "custom_sound.m4a"
		}

        // /o/ 이후부터 ? 이전까지 추출
        var encodedPath = String(self[oRange.upperBound...])
        if let queryIndex = encodedPath.firstIndex(of: "?") {
            encodedPath = String(encodedPath[..<queryIndex])
        }

        // URL 디코딩 후 마지막 컴포넌트 추출
        let decodedPath = encodedPath.removingPercentEncoding ?? encodedPath
        return decodedPath.components(separatedBy: "/").last ?? "custom_sound.m4a"
	}
}

파일명 추출 동작

// Before
let pathComponents = downloadURL.path.components(separatedBy: "/")
let fileName = pathComponents.last ?? "custom_sound.m4a"

// After
let fileName = soundURLString.firebaseStorageFileName
> 결과 -> "UUID.m4a"

2. 새로 생성된 키링의 사운드를 캐시에 복사

KeyringInfoInputView+FirebaseSave.swift

private func copySoundToCache(localURL: URL, firebaseURL: String) {
    let soundsDir = cacheDirectory.appendingPathComponent("sounds")
    let fileName = firebaseURL.firebaseStorageFileName
    let destinationURL = soundsDir.appendingPathComponent(fileName)

    try FileManager.default.copyItem(at: localURL, to: destinationURL)
}

이후, viewModel.soundId 업데이트를 해주고 URL 추출 처리를 해주면 됩니다.

### 왜 이런 과정이 필요한가? 

단순히, **사운드 재생(스트리밍)**을 위한 것과 **영상 재생** 위한 것은 차이가 존재했습니다.

#### 1. 실시간 재생 (AVPlayer)
> Firebase URL을 직접 스트리밍하여 재생

- 네트워크에서 실시간으로 오디오 데이터를 받아 재생
- 로컬 파일 없이도 동작

#### 2. 영상 생성 (AVMutableComposition)
> // 오디오 트랙을 비디오에 합성

```swift
let audioAsset = AVURLAsset(url: soundURL)
let audioTrack = try await audioAsset.loadTracks(withMediaType: .audio).first
compositionAudioTrack.insertTimeRange(..., of: audioTrack, at: startTime)
  • AVMutableComposition은 오디오/비디오 트랙을 파일 시스템에서 직접 읽어 합성
  • Firebase URL을 넣으면 트랙 로드 실패 → 에러 -11838
  • 반드시 로컬 캐시 파일이 필요

결론

키링 씬에서 사운드가 정상 재생되더라도,
영상 생성 시에는 동일한 사운드 파일이 로컬 캐시에 존재해야 합니다.
새로 생성된 키링의 커스텀 사운드를 즉시 캐시에 복사하여, 완성뷰에서 바로 영상 공유가 가능하도록 한 것,.

📱 스크린샷 (UI 변경 시)

스크린샷, 2026-02-09 14 36 25

잘 됩니다!

🔗 관련 이슈

✅ 체크리스트

  • 빌드 성공
  • 테스트 완료
  • Self-review 완료

3개 파일에서 동일한 로직이 중복되어 추상화했음.
- URL 형식 .../o/path%2Fto%2Ffile.m4a?token=... ~~ 에서 file.m4a 추출
- URL 인코딩된 경로 디코딩 처리
새로 생성된 키링의 커스텀 사운드가 캐시에 없어 영상 생성 실패!~
였으나 수정
- Firebase 업로드 후에, viewModel.soundId를 Firebase URL로 업뎃
- copySoundToCache: 로컬 파일을 캐시에 복사 -> 영상 생성 시 사용
- extractFileName 중복 제거 -> String 익스텐션에서 사용
Firebase URL path에서 잘못된 파일명을 추출하던 버그 수정
- 기존: downloadURL.path.last → URL 인코딩된 전체 경로 반환
- 수정: firebaseStorageFileName → /o/ 이후 경로를 디코딩하여 실제 파일명 추출
- 불필요한 디버그 로그 제거
@freshfresh22
Copy link
Copy Markdown
Member

빨리 업데이트 해조

}


// MARK: - 로컬 사운드 파일을 캐시에 복사
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

결국 이 사운드 파일도 캐시에 있어야 했네요... 그래도 명확한 해결방안이네요!
이전에 선물 주고 받는 것도 녹음 파일이 문제였는데 이래저래 손이 많이 가는 녀석...

@giljihun giljihun merged commit 2284f97 into develop Feb 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bugfix: [키링 만들기] - 커스텀 사운드 사용 키링/영상 미생성 버그

3 participants