forked from DGI-USC/usc_mirc_microservices_plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
usc_mirc_microservices_plugin.py
137 lines (118 loc) · 5.94 KB
/
usc_mirc_microservices_plugin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
from islandoraUtils.fedoraLib import update_datastream
from plugin_manager import IslandoraListenerPlugin
import ConfigParser
from converter import FFMpeg
import os
from lxml import etree
import requests
class usc_mirc_microservices_plugin(IslandoraListenerPlugin):
def initialize(self, config_parser):
IslandoraListenerPlugin.initialize(self, config_parser)
try:
self.islandora_url = config_parser.get('MIRC', 'url')
self.islandora_create_access_endpoint = self.islandora_url + '/' + config_parser.get('MIRC', 'create_access_endpoint')
self.islandora_username = config_parser.get('MIRC', 'username')
self.islandora_password = config_parser.get('MIRC', 'password')
self.stream_output_path = config_parser.get('MIRC', 'output_path')
if not os.path.isdir(self.stream_output_path):
self.logger.error('Transcode output path does not exist, or is not a directory!')
return False
bug_name = config_parser.get('MIRC', 'bug_name')
self.bug_path = os.path.realpath(os.path.join(os.path.dirname(__file__), bug_name))
if not os.path.isfile(self.bug_path):
self.logger.error('File at bug path does not exist!')
return False
except ConfigParser.Error:
self.logger.exception('Failed to read values from config.')
return False
self.f = FFMpeg()
self.requests_session = requests.Session()
return True
def fedoraMessage(self, message, obj, client):
if 'usc:mezzanineCModel' in message['content_models'] and message['method'] == 'ingest' and 'PBCORE' in obj:
data = {
'parent': obj.pid
}
# Get the mezz path from the PBCore.
# /pb:pbcoreInstantiationDocument/pb:instantiationIdentifier[@source="filename"]
pbcore = etree.fromstring(obj['PBCORE'].getContent().read())
path = pbcore.xpath('/pb:pbcoreInstantiationDocument/pb:instantiationIdentifier[@source="filename"]', namespaces={
'pb': 'http://www.pbcore.org/PBCore/PBCoreNamespace.html'
})
if len(path) > 0:
path = path[0].text
else:
self.logger.warning('Missing path in PBCore.')
# Throw the mezz path at the access copy function, and create a child as an access copy.
data['video_path'] = self.produceVideoAccessCopy(path)
# Throw the mezz path at the thumbnail function, and store the thumbnail somewhere.
data['thumbnail_path'] = self.produceThumbnail(path)
# Throw the paths to the access copy and thumbnail at Islandora.
r = self.requests_session.post(self.islandora_create_access_endpoint, data=data)
if r.status_code == requests.codes.forbidden:
# first attempt might fail due to an expired session... Let's try to authenticate, and try again.
r = self.requests_session.post(self.islandora_url + '/user/login', data={
'name': self.islandora_username,
'pass': self.islandora_password,
'form_id': 'user_login',
}, headers={'content-type': 'application/x-www-form-urlencoded'})
r = self.requests_session.post(self.islandora_create_access_endpoint, data=data)
update_datastream(obj, 'TN', data['thumbnail_path'], label='Thumbnail', mimeType='image/png')
os.remove(data['thumbnail_path'])
if r.status_code == requests.codes.created:
self.logger.info('Islandora created new access variant.')
else:
self.logger.warning('Islandora failed to create the new access variant.')
'''
Create an access copy with FFMpeg, and return the path to where it is.
@return
A string, indicating where the access copy was created.
'''
def produceVideoAccessCopy(self, filename):
basename = os.path.basename(filename)
base, ext = os.path.splitext(basename)
output_name = os.path.join(self.stream_output_path, base + '_Acc.m4v')
info = self.f.probe(filename)
# For mezzanines that are not 1920 pixels wide deinterlace if necessary and scale
if info.video.video_width != 1920:
conv = self.f.convert(filename, output_name, opts=[
'-i', self.bug_path,
'-filter_complex', 'yadif,scale=-2:360,overlay=10:main_h-overlay_h-10',
'-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-b:v', '786k',
'-c:a', 'libvo_aacenc',
'-movflags', 'faststart'
],timeout=False)
# For mezzanines that are 1920 pixels wide, crop to remove pillar box and scale
else:
conv = self.f.convert(filename, output_name, opts=[
'-i', self.bug_path,
'-filter_complex', 'crop=1440:in_h:240:0,scale=-2:360,overlay=10:main_h-overlay_h-10',
'-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-b:v', '786k',
'-c:a', 'libvo_aacenc',
'-movflags', 'faststart'
], timeout=False)
for timecode in conv:
pass
return output_name
'''
Create a thumbnail with FFMpeg.
@return
A file object
'''
def produceThumbnail(self, filename):
basename = os.path.basename(filename)
base, ext = os.path.splitext(basename)
output_name = os.path.join(self.stream_output_path, base + '_thumbnail.png')
# Again test for width
if info.video.video_width != 1920:
thumb = self.f.convert(filename, output_name, opts=[
'-vf', 'yadif,scale=480:360,thumbnail=80','-frames:v', '1'
])
else:
thumb = self.f.convert(filename, output_name, opts=[
'-vf', 'crop=1440:in_h:240:0,scale=480:360,thumbnail=80',
'-frames:v', '1'
])
for timecode in thumb:
pass
return output_name