Skip to the content.

如何获取一个会议的 transcripts

Teams 开发团队在过去半年里提供了很多的关于会议的 api,这让我们又有了很多的可以实现的功能和场景。今天我要介绍的是如何获取会议的 transcripts。

首先我们要知道的一个概念是:一个会议 meeting 可能有很多的 transcript,是一对多的关系,而不是一对一的关系。看到这里,对于熟悉 teams api 和 graph api 的读者可能已经在脑海里有了一个这样的api的:GET meetings/{meetingId}/transcripts,恭喜你,你已经对微软的 api 设计有了非常好的 sense。

我们来看一下官方的 api 定义:

  • 获取transcript列表
GET /me/onlineMeetings/{meetingId}/transcripts
GET /users/{userId}/onlineMeetings/{meetingId}/transcripts
  • 获取某一个具体的 transcript 的内容
GET me/onlineMeetings/{meetingId}/transcripts/{transcriptId}/content
GET users/{userId}/onlineMeetings/{meetingId}/transcripts/{transcriptId}/content

看到这里大家是不是已经开始准备撸起袖子开干了?不要急,这里面最困难的是如何获取 meetingId,说实话,我觉得微软已经提供一些更好的方法让我们获取 meeting id,但现实是到写这篇文章开始,还没有特别好的方法,官方提供的有两种方法:

方法一:订阅消息

可以订阅用户级别或者是整个租户级别的消息,通过这个 api:POST https://graph.microsoft.com/v1.0/subscriptions/

这里我不在展开讲,因为这个topic 很大,我会专门写一篇文章来完整的介绍如何订阅各种消息。

当我们接受到了推送过来的 event,就可以通过 event 来获取会议的 joinURL,然后在通过这个 api GET https://graph.microsoft.com/v1.0/users/{userId}/onlineMeetings?$filter=JoinWebUrl%20eq%20'{joinURL}'

这种方法实际上比较麻烦,我自己做的时候也废了较多时间,所以我建议大家使用方法二。

方法二:通过Bot Framework

我们的bot可以很方便的获取,会议开始和会议结束的消息,所以我们可以方便的使用如下的代码获取 meeting id

protected override async Task OnTeamsMeetingEndAsync(MeetingEndEventDetails meeting, ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
    var meetingInfo = await TeamsInfo.GetMeetingInfoAsync(turnContext);
    var meetingId = meetingInfo.Details.MsGraphResourceId;
    ...
}

是不是很简单?大家可以会问为什么叫 MsGraphResourceId,我也不清楚,可能因为内部实现的原因,Teams sdk和api在快速发展,可能后面会用更加统一的容易理解的名字。

获取 transcript 内容

有了 meeting id,我们就已经完成了50%,使用如下的代码就可以获取所有的 transcripts。

var getTranscriptsRequest = new HttpRequestMessage(HttpMethod.Get, $"https://graph.microsoft.com/beta/users/{userId}/onlineMeetings/{meetingId}/transcripts");
getTranscriptsRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", access_Token);
var response = await httpClient.SendAsync(getTranscriptsRequest);
var content = await response.Content.ReadAsStringAsync();
var transcripts = (JObject.Parse(content)["value"]).ToObject<List<Transcripts>>();
foreach (var transcript in transcripts)
{
    var getTranscriptReqest = new HttpRequestMessage(HttpMethod.Get, $"https://graph.microsoft.com/beta/users/{userId}/onlineMeetings/{meetingId}/transcripts/{transcripts.FirstOrDefault().Id}/content?$format=text/vtt");
    getTranscriptReqest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", access_Token);
    var transcriptResponse = await client.SendAsync(getTranscriptReqest);
    var transcriptContent = await transcriptResponse.Content.ReadAsStringAsync();
    ...
}

可以看到上面的代码里面,我们先调用了 users/{userId}/onlineMeetings/{meetingId}/transcripts 来获取针对某个会议的所有 transcripts,然后我们就枚举每一个 transcript,通过 api users/{userId}/onlineMeetings/{meetingId}/transcripts/{transcriptId}/content?$format=text/vtt 获取具体的内容,可以看到我们加了一个 query string format=text/vtt,这么做的好处是我觉得这个格式处理起来比较简单。大致的格式如下。

HTTP/1.1 200 OK
Content-type: text/vtt

WEBVTT

0:0:0.0 --> 0:0:6.580
This is a test from Tony.

0:0:12.1 --> 0:0:18.720
Hello Teams.

如果大家对于其他格式比较感兴趣,可以查看这个api的官方文档。 https://docs.microsoft.com/en-us/graph/api/calltranscript-get?view=graph-rest-beta&tabs=http

Written on September 5, 2022