feat: sync GIFv and saved GIF support
This commit is contained in:
parent
c0088f1160
commit
5f7c0b9804
21 changed files with 641 additions and 50 deletions
|
|
@ -109,6 +109,9 @@ type DocumentSpec struct {
|
|||
Attributes []DocumentAttribute
|
||||
Thumb *UploadedFileRef // 可选缩略图上传,生成 doc:<id>:m
|
||||
ForceFile bool
|
||||
// NosoundVideo 对应 inputMediaUploadedDocument.nosound_video。真实 GIF 仍会
|
||||
// 转成 MP4,但该标志存在时按普通无声视频落库,不附 animated 属性(album 路径)。
|
||||
NosoundVideo bool
|
||||
}
|
||||
|
||||
// FileDownloadRequest 是 upload.getFile 解析后的下载请求;
|
||||
|
|
@ -205,6 +208,8 @@ type DocumentAttribute struct {
|
|||
Duration float64 `json:"duration,omitempty"`
|
||||
RoundMessage bool `json:"round_message,omitempty"`
|
||||
SupportsStreaming bool `json:"supports_streaming,omitempty"`
|
||||
NoSound bool `json:"no_sound,omitempty"`
|
||||
VideoCodec string `json:"video_codec,omitempty"`
|
||||
|
||||
// audio
|
||||
AudioDuration int `json:"audio_duration,omitempty"`
|
||||
|
|
@ -350,14 +355,24 @@ func (d Document) stickerMaterialMimeOrExt() string {
|
|||
return mimeType
|
||||
}
|
||||
|
||||
// IsGif reports whether the document is a savable GIF (documentAttributeAnimated).
|
||||
// IsGif reports whether the document is a canonical, savable Telegram GIFv.
|
||||
// Telegram 的 GIF 是无声 MP4;仅有 animated 属性的 raw image/gif 不是合法 saved GIF。
|
||||
func (d Document) IsGif() bool {
|
||||
if !strings.EqualFold(strings.TrimSpace(d.MimeType), "video/mp4") {
|
||||
return false
|
||||
}
|
||||
var animated, video bool
|
||||
for _, attr := range d.Attributes {
|
||||
if attr.Kind == DocAttrAnimated {
|
||||
return true
|
||||
switch attr.Kind {
|
||||
case DocAttrAnimated:
|
||||
animated = true
|
||||
case DocAttrVideo:
|
||||
if !attr.RoundMessage && attr.W > 0 && attr.H > 0 && attr.Duration > 0 {
|
||||
video = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
return animated && video
|
||||
}
|
||||
|
||||
// Photo 是已存储的 Telegram 照片(头像或图片消息)。
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ func ClassifyMediaCategories(media *MessageMedia, entities []MessageEntity) []Me
|
|||
}
|
||||
|
||||
// classifyDocumentCategory 按 TL DocumentAttribute 判定一个文档落入哪个媒体类别。
|
||||
// 客户端的标签页 UI 以 TL 属性(而非 MIME)为准,故这里也只看属性。优先级:
|
||||
// sticker(不入任何标签页)> animated(GIF) > audio(music/voice) > video(video/round) > 通用文件。
|
||||
// 客户端的标签页 UI 以 TL 属性和 GIFv MIME 共同判定。优先级:sticker(不入任何标签页)>
|
||||
// canonical animated MP4 (GIF) > audio(music/voice) > video(video/round) > 通用文件。
|
||||
func classifyDocumentCategory(doc *Document) (MediaCategory, bool) {
|
||||
if doc == nil {
|
||||
return MediaCategoryNone, false
|
||||
|
|
@ -130,7 +130,7 @@ func classifyDocumentCategory(doc *Document) (MediaCategory, bool) {
|
|||
switch {
|
||||
case hasSticker:
|
||||
return MediaCategoryNone, false // 贴纸/自定义 emoji 不出现在共享媒体
|
||||
case hasAnimated:
|
||||
case hasAnimated && doc.IsGif():
|
||||
return MediaCategoryGif, true
|
||||
case hasAudio:
|
||||
if audioVoice {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ func TestClassifyMediaCategories(t *testing.T) {
|
|||
{"poll", &MessageMedia{Kind: MessageMediaKindPoll}, nil, []MediaCategory{MediaCategoryPoll}},
|
||||
{"video", doc(DocumentAttribute{Kind: DocAttrVideo}), nil, []MediaCategory{MediaCategoryVideo}},
|
||||
{"round video note", doc(DocumentAttribute{Kind: DocAttrVideo, RoundMessage: true}), nil, []MediaCategory{MediaCategoryRoundVideo}},
|
||||
{"gif animation", doc(DocumentAttribute{Kind: DocAttrAnimated}), nil, []MediaCategory{MediaCategoryGif}},
|
||||
{"gif animation", &MessageMedia{Kind: MessageMediaKindDocument, Document: &Document{MimeType: "video/mp4", Attributes: []DocumentAttribute{{Kind: DocAttrAnimated}, {Kind: DocAttrVideo, W: 320, H: 240, Duration: 1}}}}, nil, []MediaCategory{MediaCategoryGif}},
|
||||
{"raw gif is a file", &MessageMedia{Kind: MessageMediaKindDocument, Document: &Document{MimeType: "image/gif", Attributes: []DocumentAttribute{{Kind: DocAttrAnimated}}}}, nil, []MediaCategory{MediaCategoryFile}},
|
||||
{"music", doc(DocumentAttribute{Kind: DocAttrAudio}), nil, []MediaCategory{MediaCategoryMusic}},
|
||||
{"voice", doc(DocumentAttribute{Kind: DocAttrAudio, Voice: true}), nil, []MediaCategory{MediaCategoryVoice}},
|
||||
{"generic file", doc(DocumentAttribute{Kind: DocAttrFilename, FileName: "x.pdf"}), nil, []MediaCategory{MediaCategoryFile}},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue