fix(storage): add panic recovery for malformed MP4 files

- Add defer/recover in getMP4Meta to catch panics from gomedia library
- Implement fallback to ffprobe when MP4 parsing fails
- Fixes "no vosdata" panic when processing certain MP4 files

Also add CLAUDE.md to provide architecture guidance for AI coding assistants.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
krau
2025-12-31 20:36:26 +08:00
parent 8dd6265d55
commit 0e951f641c
3 changed files with 188 additions and 4 deletions

View File

@@ -181,6 +181,11 @@ func (t *Telegram) Save(ctx context.Context, r io.Reader, storagePath string) er
switch mtypeStr {
case "video/mp4":
info, err := getMP4Meta(rs)
if err != nil {
// Fallback to ffprobe if gomedia fails (e.g., malformed MP4)
rs.Seek(0, io.SeekStart)
info, err = getVideoMetadata(rs)
}
if err == nil {
media = doc.Video().
Duration(time.Duration(info.Duration)*time.Second).

View File

@@ -21,12 +21,19 @@ type VideoMetadata struct {
}
// a go native way to get mp4 video metadata
func getMP4Meta(rs io.ReadSeeker) (*VideoMetadata, error) {
func getMP4Meta(rs io.ReadSeeker) (metadata *VideoMetadata, err error) {
// Recover from panics in the gomedia library (e.g., "no vosdata" panic)
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic while parsing MP4: %v", r)
}
}()
d := mp4.CreateMp4Demuxer(rs)
tracks, err := d.ReadHead()
if err != nil {
return nil, err
tracks, e := d.ReadHead()
if e != nil {
return nil, e
}
for _, track := range tracks {